Merge branch 'master' into feature/objc-sessionmanager-merge

* master: (682 commits)
  fix, tests for #2500
  added sample files
  rebuilt sample
  changed to use tag sanitization method
  Update doc to support resteasy
  add petstore yaml
  fix typo, update sinatra to use origianl petstore spec (yaml)
  made timestamp generation enabled by default
  rebuilt with generation timestamp disabled
  rebuilt
  added bootstrap sample
  added script
  made generation timestamp optional
  added bootstrap, renamed sample
  added bootstrap
  updated templates
  add new model in csharp
  minor fix to docstring in csharp
  add new files for perl, php, ruby
  add new files for JS
  ...
This commit is contained in:
Wolfgang Berger 2016-04-06 11:14:24 +02:00
commit 0259c45b7a
2038 changed files with 116031 additions and 53194 deletions

103
.gitignore vendored
View File

@ -13,33 +13,6 @@ generated-sources/*
generated-code/*
*.swp
*.swo
*.csproj.user
/target
/generated-files
/nbactions.xml
*.pyc
__pycache__
samples/server-generator/scalatra/output
samples/server-generator/node/output/node_modules
samples/server-generator/scalatra/target
samples/server-generator/scalatra/output/.history
samples/client/petstore/qt5cpp/PetStore/moc_*
samples/client/petstore/qt5cpp/PetStore/*.o
samples/client/petstore/objc/PetstoreClient.xcworkspace/xcuserdata
samples/client/petstore/qt5cpp/build-*
samples/client/petstore/qt5cpp/PetStore/PetStore
samples/client/petstore/qt5cpp/PetStore/Makefile
samples/client/petstore/java/hello.txt
samples/client/petstore/android/default/hello.txt
samples/client/petstore/objc/SwaggerClientTests/Build
samples/client/petstore/objc/SwaggerClientTests/Pods
samples/client/petstore/objc/SwaggerClientTests/SwaggerClient.xcworkspace
samples/client/petstore/objc/SwaggerClientTests/Podfile.lock
samples/server/petstore/nodejs/node_modules
samples/client/petstore/csharp/SwaggerClientTest/.vs
samples/client/petstore/csharp/SwaggerClientTest/obj
samples/client/petstore/csharp/SwaggerClientTest/bin
target
.idea
.lib
@ -48,15 +21,7 @@ atlassian-ide-plugin.xml
packages/
.pub
.packages
samples/client/petstore/php/SwaggerClient-php/composer.lock
samples/client/petstore/php/SwaggerClient-php/vendor/
samples/client/petstore/silex/SwaggerServer/composer.lock
samples/client/petstore/silex/SwaggerServer/venodr/
samples/client/petstore/python/.projectile
samples/client/petstore/python/.venv/
.vagrant/
.settings
@ -65,3 +30,69 @@ samples/client/petstore/python/.venv/
*.pm~
*.xml~
*.t~
/target
/generated-files
/nbactions.xml
# scalatra
samples/server-generator/scalatra/output
samples/server-generator/scalatra/target
samples/server-generator/scalatra/output/.history
# nodejs
samples/server-generator/node/output/node_modules
samples/server/petstore/nodejs/node_modules
# qt5 cpp
samples/client/petstore/qt5cpp/PetStore/moc_*
samples/client/petstore/qt5cpp/PetStore/*.o
samples/client/petstore/qt5cpp/build-*
samples/client/petstore/qt5cpp/PetStore/PetStore
samples/client/petstore/qt5cpp/PetStore/Makefile
#Java/Android
**/.gradle/
samples/client/petstore/java/hello.txt
samples/client/petstore/android/default/hello.txt
#PHP
samples/client/petstore/php/SwaggerClient-php/composer.lock
samples/client/petstore/php/SwaggerClient-php/vendor/
samples/client/petstore/silex/SwaggerServer/composer.lock
samples/client/petstore/silex/SwaggerServer/venodr/
# Perl
samples/client/petstore/perl/deep_module_test/
# Objc
samples/client/petstore/objc/PetstoreClient.xcworkspace/xcuserdata
samples/client/petstore/objc/SwaggerClientTests/SwaggerClient.xcodeproj/xcuserdata
samples/client/petstore/objc/SwaggerClientTests/Build
samples/client/petstore/objc/SwaggerClientTests/Pods
samples/client/petstore/objc/SwaggerClientTests/SwaggerClient.xcworkspace
samples/client/petstore/objc/SwaggerClientTests/Podfile.lock
# Swift
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
# C#
*.csproj.user
samples/client/petstore/csharp/SwaggerClientTest/.vs
samples/client/petstore/csharp/SwaggerClientTest/obj
samples/client/petstore/csharp/SwaggerClientTest/bin
samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/vendor/
samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/
samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/
# Python
*.pyc
__pycache__
samples/client/petstore/python/dev-requirements.txt.log
samples/client/petstore/python/swagger_client.egg-info/SOURCES.txt
samples/client/petstore/python/.coverage
samples/client/petstore/python/.projectile
samples/client/petstore/python/.venv/

View File

@ -2,6 +2,7 @@ sudo: required
language: java
jdk:
- oraclejdk7
- oraclejdk8
services:
- docker
@ -11,12 +12,10 @@ before_install:
- gem install bundler
install:
- docker login --email=$DOCKER_HUB_EMAIL --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD
script:
- mvn verify -Psamples
- docker build -t $DOCKER_IMAGE_NAME ./modules/swagger-generator
- if [ ! -z "$TRAVIS_TAG" ]; then docker tag $DOCKER_IMAGE_NAME:latest $DOCKER_IMAGE_NAME:$TRAVIS_TAG; fi && docker push $DOCKER_IMAGE_NAME
- if [ $DOCKER_HUB_USERNAME ]; then docker login --email=$DOCKER_HUB_EMAIL --username=$DOCKER_HUB_USERNAME --password=$DOCKER_HUB_PASSWORD && docker build -t $DOCKER_IMAGE_NAME ./modules/swagger-generator && if [ ! -z "$TRAVIS_TAG" ]; then docker tag $DOCKER_IMAGE_NAME:latest $DOCKER_IMAGE_NAME:$TRAVIS_TAG; fi && docker push $DOCKER_IMAGE_NAME; fi
env:
- DOCKER_IMAGE_NAME=swaggerapi/swagger-generator

View File

@ -2,7 +2,7 @@
## 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 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
@ -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:
- C#: https://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx
- 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
- 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/
- 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

View File

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

274
README.md
View File

@ -1,7 +1,8 @@
# 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)
[![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:
@ -22,7 +23,8 @@ Check out [Swagger-Spec](https://github.com/OAI/OpenAPI-Specification) for addit
- [Building](#building)
- [Docker](#docker)
- [Build and run](#build-and-run-using-docker)
- [Build a Node.js server stub](#build-a-nodejs-server-stub)
- [Run docker in Vagrant](#run-docker-in-vagrant)
- [Public Docker image](#public-docker-image)
- [Homebrew](#homebrew)
- Generators
- [To generate a sample client library](#to-generate-a-sample-client-library)
@ -32,21 +34,28 @@ Check out [Swagger-Spec](https://github.com/OAI/OpenAPI-Specification) for addit
- [Where is Javascript???](#where-is-javascript)
- [Generating a client from local files](#generating-a-client-from-local-files)
- [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 static html api documentation](#generating-static-html-api-documentation)
- [To build a server stub](#to-build-a-server-stub)
- [Node.js](#nodejs)
- [PHP Slim](#php-slim)
- [PHP Silex](#php-silex)
- [Python Flask (Connexion)](#python-flask-connexion)
- [Ruby Sinatra](#ruby-sinatra)
- [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 JAX-RS (Resteasy)](#java-jax-rs-resteasy)
- [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)
- [Workflow Integration](#workflow-integration)
- [Github Integration](#github-integration)
- [Online Generators](#online-generators)
- [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)
@ -56,16 +65,16 @@ The OpenAPI Specification has undergone 3 revisions since initial creation in 20
Swagger Codegen Version | Release Date | OpenAPI Spec compatibility | Notes
-------------------------- | ------------ | -------------------------- | -----
2.1.6-SNAPSHOT | | 1.0, 1.1, 1.2, 2.0 | [master](https://github.com/swagger-api/swagger-codegen)
2.1.5 (**current stable**) | 2015-01-06 | 1.0, 1.1, 1.2, 2.0 | [tag v2.1.5](https://github.com/swagger-api/swagger-codegen/tree/v2.1.4)
2.1.5 (**current stable**) | 2015-01-06 | 1.0, 1.1, 1.2, 2.0 | [tag v2.1.5](https://github.com/swagger-api/swagger-codegen/tree/v2.1.5)
2.0.17 | 2014-08-22 | 1.1, 1.2 | [tag v2.0.17](https://github.com/swagger-api/swagger-codegen/tree/v2.0.17)
1.0.4 | 2012-04-12 | 1.0, 1.1 | [tag v1.0.4](https://github.com/swagger-api/swagger-codegen/tree/swagger-codegen_2.9.1-1.1)
### Prerequisites
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
```
@ -77,16 +86,16 @@ brew install swagger-codegen
To build from source, you need the following installed and available in your $PATH:
* [Java 7](http://java.oracle.com)
* [Java 7 or 8](http://java.oracle.com)
* [Apache maven 3.0.3 or greater](http://maven.apache.org/)
* [Apache maven 3.3.3 or greater](http://maven.apache.org/)
#### OS X Users
Don't forget to install Java 7. You probably have 1.6 or 1.8.
Don't forget to install Java 7 or 8. You probably have 1.6.
Export JAVA_HOME in order to use the supported Java version:
```
export JAVA_HOME=`/usr/libexec/java_home -v 1.7`
export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
export PATH=${JAVA_HOME}/bin:$PATH
```
@ -102,21 +111,27 @@ mvn package
```
git clone https://github.com/swagger-api/swagger-codegen
cd swagger-codegen
./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 \
-i http://petstore.swagger.io/v2/swagger.json \
-l nodejs \
-o samples/server/petstore/nodejs
git clone http://github.com/swagger-api/swagger-codegen.git
cd swagger-codegen
vagrant up
vagrant ssh
cd /vagrant
./run-in-docker.sh mvn package
```
#### Public Docker image
https://hub.docker.com/r/swaggerapi/swagger-generator/
### Homebrew
To install, run `brew install swagger-codegen`
@ -148,18 +163,27 @@ with a number of options. You can get the options with the `help generate` comm
```
NAME
swagger generate - Generate code with chosen lang
swagger-codegen-cli generate - Generate code with chosen lang
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>)]
[-D <system properties>]
[-D <system properties>] [--group-id <group id>]
(-i <spec file> | --input-spec <spec file>)
[--import-mappings <import mappings>]
[--instantiation-types <instantiation types>]
[--invoker-package <invoker package>]
(-l <language> | --lang <language>)
[--language-specific-primitives <language specific primitives>]
[--library <library>] [--model-package <model package>]
[(-o <output directory> | --output <output directory>)]
[(-t <template directory> | --template-dir <template directory>)]
[(-v | --verbose)]
[(-s | --skip-overwrite)]
[(-t <template directory> | --template-dir <template directory>)]
[--type-mappings <type mappings>] [(-v | --verbose)]
OPTIONS
-a <authorization>, --auth <authorization>
@ -167,6 +191,19 @@ OPTIONS
remotely. Pass in a URL-encoded string of name:header with a comma
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>
Path to json configuration file. File content should be in a json
format {"optionKey":"optionValue", "optionKey1":"optionValue1"...}
@ -177,25 +214,59 @@ OPTIONS
sets specified system properties in the format of
name=value,name=value
--group-id <group id>
groupId in generated pom.xml
-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>
client language to generate (maybe class name in classpath,
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>
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>
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
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:
@ -232,16 +303,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:
```
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:
```
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 \
-o myClient
```
@ -299,10 +369,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/
AbstractJavaJAXRSServerCodegen.java
AbstractTypeScriptClientCodegen.java
AkkaScalaClientCodegen.java
AndroidClientCodegen.java
AndroidVolleyClientCodegen.java
AspNet5ServerCodegen.java
AsyncScalaClientCodegen.java
CSharpClientCodegen.java
ClojureClientCodegen.java
@ -310,11 +381,15 @@ CsharpDotNet2ClientCodegen.java
DartClientCodegen.java
FlashClientCodegen.java
FlaskConnexionCodegen.java
GoClientCodegen.java
HaskellServantCodegen.java
JMeterCodegen.java
JavaCXFServerCodegen.java
JavaClientCodegen.java
JavaInflectorServerCodegen.java
JavaJerseyServerCodegen.java
JavaResteasyServerCodegen.java
JavascriptClientCodegen.java
JaxRSServerCodegen.java
JMeterCodegen.java
NodeJSServerCodegen.java
ObjcClientCodegen.java
PerlClientCodegen.java
@ -398,12 +473,12 @@ CONFIG OPTIONS
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",
"artifactId":"MyClent",
"artifactId":"MyClient",
"artifactVersion":"1.2.0",
"library":"feign"
}
@ -414,7 +489,7 @@ 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.
To change, for example, the prefix for the Objective-C generated files, simply subclass the ObjcClientCodegen.java:
```
```java
package com.mycompany.swagger.codegen;
import io.swagger.codegen.languages.*;
@ -494,6 +569,15 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-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
```
@ -508,7 +592,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 \
-i http://petstore.swagger.io/v2/swagger.json \
-l flaskConnexion \
-l python-flask \
-o samples/server/petstore/flaskConnexion
```
@ -529,13 +613,47 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-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 \
-i http://petstore.swagger.io/v2/swagger.json \
-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 JAX-RS (Resteasy)
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l jaxrs-resteasy \
-o samples/server/petstore/jaxrs-resteasy
```
### Java Spring MVC
@ -547,6 +665,24 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-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
This will create the swagger-codegen library from source.
@ -561,6 +697,26 @@ Note! The templates are included in the library generated. If you want to modi
You can use the [swagger-codegen-maven-plugin](modules/swagger-codegen-maven-plugin/README.md) for integrating with your workflow, and generating any codegen target.
## GitHub Integration
To push the auto-generated SDK to GitHub, we provide `git_push.sh` to streamline the process. For example:
1) Create a new repository in GitHub (Ref: https://help.github.com/articles/creating-a-new-repository/)
2) Generate the SDK
```
java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \
-i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l perl \
--git-user-id "wing328" \
--git-repo-id "petstore-perl" \
--release-note "Github integration demo" \
-o /var/tmp/perl/petstore
```
3) Push the SDK to GitHub
```
cd /var/tmp/perl/petstore
/bin/sh ./git_push.sh
```
## Online generators
@ -577,10 +733,43 @@ Guidelines for Contribution
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/)
- [beemo](http://www.beemo.eu)
- [CloudBoost](https://www.CloudBoost.io/)
- [Cupix](http://www.cupix.com)
- [DocuSign](https://www.docusign.com)
- [Ergon](http://www.ergon.ch/)
- [eureka](http://eure.jp/)
- [everystory.us](http://everystory.us)
- [Expected Behavior](http://www.expectedbehavior.com/)
- [FH Münster - University of Applied Sciences](http://www.fh-muenster.de)
- [LANDR Audio](https://www.landr.com/)
- [LiveAgent](https://www.ladesk.com/)
- [Kuary](https://kuary.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
-------
Copyright 2015 SmartBear Software
Copyright 2016 SmartBear Software
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -591,3 +780,6 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
---
<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/csharp-petstore.sh
./bin/dynamic-html.sh
./bin/haskell-petstore.sh
./bin/html-petstore.sh
./bin/java-petstore.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

@ -26,6 +26,6 @@ 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 -o samples/client/petstore/java/default"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l java -o samples/client/petstore/java/default -DhideGenerationTimestamp=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.
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

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.yaml -l jaxrs-cxf -o samples/server/petstore/jaxrs-cxf -DhideGenerationTimestamp=true"
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.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaJaxRS -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l jaxrs -o samples/server/petstore/jaxrs"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaJaxRS -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l jaxrs -o samples/server/petstore/jaxrs -DhideGenerationTimestamp=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 -t modules/swagger-codegen/src/main/resources/JavaJaxRS -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l jaxrs-resteasy -o samples/server/petstore/jaxrs-resteasy -DhideGenerationTimestamp=true"
java $JAVA_OPTS -jar $executable $ags

31
bin/jersey2-petstore-server.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/JavaJaxRS -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l jaxrs -o samples/server/petstore/jersey2 --library=jersey2 -DhideGenerationTimestamp=true"
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.
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 nodejs -o samples/server/petstore/nodejs"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l nodejs-server -o samples/server/petstore/nodejs"
java $JAVA_OPTS -Dservice -jar $executable $ags

View File

@ -26,6 +26,9 @@ 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"
# complex module name used for testing
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l perl -o samples/client/petstore/perl"
java $JAVA_OPTS -jar $executable $ags
java $JAVA_OPTS -jar $executable $ags --additional-properties moduleName=Something::Deep -o samples/client/petstore/perl/deep_module_test

View File

@ -26,6 +26,6 @@ fi
# if you've executed sbt assembly previously it will use that instead.
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

View File

@ -26,6 +26,6 @@ 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/sinatra -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l sinatra -o samples/server/petstore/sinatra"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/sinatra -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l sinatra -o samples/server/petstore/sinatra"
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

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

View File

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

View File

@ -5,18 +5,11 @@ import io.airlift.airline.Option;
import io.swagger.codegen.ClientOptInput;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.DefaultGenerator;
import io.swagger.codegen.cmd.utils.OptionUtils;
import io.swagger.codegen.config.CodegenConfigurator;
import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static io.swagger.codegen.config.CodegenConfiguratorUtils.*;
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)
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." +
"For example (in Java): array=ArrayList,map=HashMap. In other words array types will get instantiated as ArrayList in generated code.")
private String instantiationTypes;
@ -107,6 +106,18 @@ public class Generate implements Runnable {
@Option(name = {"--library"}, title = "library", description = CodegenConstants.LIBRARY_DESC)
private String library;
@Option(name = {"--git-user-id"}, title = "git user id", description = CodegenConstants.GIT_USER_ID_DESC)
private String gitUserId;
@Option(name = {"--git-repo-id"}, title = "git repo id", description = CodegenConstants.GIT_REPO_ID_DESC)
private String gitRepoId;
@Option(name = {"--release-note"}, title = "release note", description = CodegenConstants.RELEASE_NOTE_DESC)
private String releaseNote;
@Option(name = {"--http-user-agent"}, title = "http user agent", description = CodegenConstants.HTTP_USER_AGENT_DESC)
private String httpUserAgent;
@Override
public void run() {
@ -156,6 +167,14 @@ public class Generate implements Runnable {
configurator.setModelPackage(modelPackage);
}
if(isNotEmpty(modelNamePrefix)){
configurator.setModelNamePrefix(modelNamePrefix);
}
if(isNotEmpty(modelNameSuffix)){
configurator.setModelNameSuffix(modelNameSuffix);
}
if(isNotEmpty(invokerPackage)) {
configurator.setInvokerPackage(invokerPackage);
}
@ -176,74 +195,31 @@ public class Generate implements Runnable {
configurator.setLibrary(library);
}
setSystemProperties(configurator);
setInstantiationTypes(configurator);
setImportMappings(configurator);
setTypeMappings(configurator);
setAdditionalProperties(configurator);
setLanguageSpecificPrimitives(configurator);
if (isNotEmpty(gitUserId)) {
configurator.setGitUserId(gitUserId);
}
if (isNotEmpty(gitRepoId)) {
configurator.setGitRepoId(gitRepoId);
}
if (isNotEmpty(releaseNote)) {
configurator.setReleaseNote(releaseNote);
}
if (isNotEmpty(httpUserAgent)) {
configurator.setHttpUserAgent(httpUserAgent);
}
applySystemPropertiesKvp(systemProperties, configurator);
applyInstantiationTypesKvp(instantiationTypes, configurator);
applyImportMappingsKvp(importMappings, configurator);
applyTypeMappingsKvp(typeMappings, configurator);
applyAdditionalPropertiesKvp(additionalProperties, configurator);
applyLanguageSpecificPrimitivesCsv(languageSpecificPrimitives, configurator);
final ClientOptInput clientOptInput = configurator.toClientOptInput();
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.")
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 MUSTACHE_EXTENSION = ".mustache";
@ -53,7 +53,7 @@ public class Meta implements Runnable {
@Override
public void run() {
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";
@ -93,7 +93,7 @@ public class Meta implements Runnable {
* @param data - map with additional params needed to process templates
* @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>() {
private DefaultGenerator generator = new DefaultGenerator();
@ -108,13 +108,13 @@ public class Meta implements Runnable {
String formatted = template;
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))
.defaultValue("")
.compile(template)
.execute(data);
} else {
LOG.info("copying file to {}", outputFile.getAbsolutePath());
LOGGER.info("copying file to {}", outputFile.getAbsolutePath());
}
FileUtils.writeStringToFile(outputFile, formatted);
@ -133,7 +133,7 @@ public class Meta implements Runnable {
* @param generator - class with reader getter
* @return loader for template
*/
private Mustache.TemplateLoader loader(final DefaultGenerator generator) {
private static Mustache.TemplateLoader loader(final DefaultGenerator generator) {
return new Mustache.TemplateLoader() {
@Override
public Reader getTemplate(String name) {
@ -149,7 +149,7 @@ public class Meta implements Runnable {
* @param packageName - package name to convert
* @return relative path
*/
private String asPath(String packageName) {
private static String asPath(String packageName) {
return packageName.replace(".", File.separator);
}
}

View File

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

View File

@ -1,5 +1,6 @@
package io.swagger.codegen.cmd.utils;
import io.swagger.codegen.utils.OptionUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.junit.Test;
@ -10,6 +11,7 @@ import java.util.List;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
@SuppressWarnings("static-method")
public class OptionUtilsTest {
@Test
@ -30,7 +32,7 @@ public class OptionUtilsTest {
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);
assertNotNull(result);
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);
assertNotNull(result);
assertEquals(result.size(), expectedResults.size());

View File

@ -6,7 +6,7 @@
<parent>
<groupId>io.swagger</groupId>
<artifactId>swagger-codegen-project</artifactId>
<version>2.1.5</version>
<version>2.1.6-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<artifactId>swagger-codegen-maven-plugin</artifactId>
@ -51,7 +51,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<!-- <version>4.12</version> -->
<scope>test</scope>
</dependency>
</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.
*/
import config.Config;
import config.ConfigParser;
import io.swagger.codegen.*;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.ClientOptInput;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.DefaultGenerator;
import io.swagger.codegen.config.CodegenConfigurator;
import io.swagger.models.Swagger;
import io.swagger.parser.SwaggerParser;
import org.apache.maven.plugin.AbstractMojo;
@ -30,15 +32,28 @@ import org.apache.maven.project.MavenProject;
import java.io.File;
import java.util.HashMap;
import java.util.HashSet;
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.
*/
@Mojo(name = "generate", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
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.
*/
@ -60,10 +75,23 @@ public class CodeGenMojo extends AbstractMojo {
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")
private String modelPackage;
@Parameter(name="auth")
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
@ -71,6 +99,12 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter(name = "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
*/
@ -78,16 +112,22 @@ public class CodeGenMojo extends AbstractMojo {
private String invokerPackage;
/**
* Client language to generate.
* groupId in generated pom.xml
*/
@Parameter(name = "language", required = true)
private String language;
@Parameter(name = "groupId")
private String groupId;
/**
* Path to separate json configuration file.
* artifactId in generated pom.xml
*/
@Parameter(name = "configurationFile", required = false)
private String configurationFile;
@Parameter(name = "artifactId")
private String artifactId;
/**
* artifact version in generated pom.xml
*/
@Parameter(name = "artifactVersion")
private String artifactVersion;
/**
* 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
*/
@Parameter(name = "configOptions")
private Map configOptions;
private Map<?, ?> configOptions;
/**
* Add the output directory to the project as a source root, so that the
@ -122,12 +162,92 @@ public class CodeGenMojo extends AbstractMojo {
@Override
public void execute() throws MojoExecutionException {
Swagger swagger = new SwaggerParser().read(inputSpec);
CodegenConfig config = CodegenConfigLoader.forName(language);
config.setOutputDir(output.getAbsolutePath());
//attempt to read from config file
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) {
for(String key : environmentVariables.keySet()) {
String value = environmentVariables.get(key);
if(value == null) {
@ -135,49 +255,22 @@ public class CodeGenMojo extends AbstractMojo {
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()) {
if (configOptions.containsKey(langCliOption.getOpt())) {
config.additionalProperties().put(langCliOption.getOpt(),
input.getConfig().additionalProperties().put(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) {
for (CliOption langCliOption : config.cliOptions()) {
System.out.println("\t" + langCliOption.getOpt());

View File

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

View File

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

View File

@ -10,12 +10,18 @@ import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.Scanner;
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 {
System.out.println("writing file " + filename);
LOGGER.info("writing file " + filename);
File output = new File(filename);
if (output.getParent() != null && !new File(output.getParent()).exists()) {
@ -36,10 +42,10 @@ public abstract class AbstractGenerator {
if (reader == null) {
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() : "";
} catch (Exception e) {
e.printStackTrace();
LOGGER.error(e.getMessage());
}
throw new RuntimeException("can't load template " + name);
}
@ -48,14 +54,11 @@ public abstract class AbstractGenerator {
try {
InputStream is = this.getClass().getClassLoader().getResourceAsStream(getCPResourcePath(name));
if (is == null) {
is = new FileInputStream(new File(name));
}
if (is == null) {
throw new RuntimeException("no file found");
is = new FileInputStream(new File(name)); // May throw but never return a null value
}
return new InputStreamReader(is);
} catch (Exception e) {
e.printStackTrace();
LOGGER.error(e.getMessage());
}
throw new RuntimeException("can't load template " + name);
}
@ -63,6 +66,10 @@ public abstract class AbstractGenerator {
/**
* Get the template file path with template dir prepended, and use the
* library template if exists.
*
* @param config Codegen config
* @param templateFile Template file
* @return String Full template file path
*/
public String getFullTemplateFile(CodegenConfig config, String templateFile) {
String library = config.getLibrary();
@ -96,6 +103,7 @@ public abstract class AbstractGenerator {
return this.getClass().getClassLoader().getResource(getCPResourcePath(name)) != null;
}
@SuppressWarnings("static-method")
public String getCPResourcePath(String name) {
if (!"/".equals(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.auth.AuthorizationValue;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
public class ClientOptInput {
private CodegenConfig config;
private ClientOpts opts;

View File

@ -1,29 +1,34 @@
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.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
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}
* or cli interface from https://github.com/swagger-api/swagger-codegen/pull/547
*/
@Deprecated
public class Codegen extends DefaultGenerator {
private static final Logger LOGGER = LoggerFactory.getLogger(Codegen.class);
static Map<String, CodegenConfig> configs = new HashMap<String, CodegenConfig>();
static String configString;
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 -DdebugSupportingFiles prints additional data passed to the template engine";
@SuppressWarnings("deprecation")
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
Options options = new Options();
options.addOption("h", "help", false, "shows this message");
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);
new Codegen().opts(clientOptInput).generate();
} catch (Exception e) {
e.printStackTrace();
LOGGER.error(e.getMessage(), e);
}
}
@ -138,9 +142,9 @@ public class Codegen extends DefaultGenerator {
} else {
// see if it's a class
try {
System.out.println("loading class " + name);
Class customClass = Class.forName(name);
System.out.println("loaded");
LOGGER.debug("loading class " + name);
Class<?> customClass = Class.forName(name);
LOGGER.debug("loaded");
return (CodegenConfig) customClass.newInstance();
} catch (Exception e) {
throw new RuntimeException("can't load class " + name);

View File

@ -19,10 +19,18 @@ public interface CodegenConfig {
Map<String, Object> additionalProperties();
Map<String, Object> vendorExtensions();
String testPackage();
String apiPackage();
String apiFileFolder();
String apiTestFileFolder();
String apiDocFileFolder();
String fileSuffix();
String outputFolder();
@ -33,6 +41,10 @@ public interface CodegenConfig {
String modelFileFolder();
String modelTestFileFolder();
String modelDocFileFolder();
String modelPackage();
String toApiName(String name);
@ -87,22 +99,42 @@ public interface CodegenConfig {
Map<String, String> modelTemplateFiles();
Map<String, String> apiTestTemplateFiles();
Map<String, String> modelTestTemplateFiles();
Map<String, String> apiDocTemplateFiles();
Map<String, String> modelDocTemplateFiles();
Set<String> languageSpecificPrimitives();
void preprocessSwagger(Swagger swagger);
void processSwagger(Swagger swagger);
String sanitizeTag(String tag);
String toApiFilename(String name);
String toModelFilename(String name);
String toApiTestFilename(String name);
String toModelTestFilename(String name);
String toApiDocFilename(String name);
String toModelDocFilename(String name);
String toModelImport(String name);
String toApiImport(String name);
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> postProcessOperations(Map<String, Object> objs);
@ -115,6 +147,10 @@ public interface CodegenConfig {
String apiFilename(String templateName, String tag);
String apiTestFilename(String templateName, String tag);
String apiDocFilename(String templateName, String tag);
boolean shouldOverwrite(String filename);
boolean isSkipOverwrite();
@ -127,6 +163,25 @@ public interface CodegenConfig {
/**
* Library template (sub-template).
*
* @return libray template
*/
String getLibrary();
void setGitUserId(String gitUserId);
String getGitUserId();
void setGitRepoId(String gitRepoId);
String getGitRepoId();
void setReleaseNote(String releaseNote);
String getReleaseNote();
void setHttpUserAgent(String httpUserAgent);
String getHttpUserAgent();
}

View File

@ -46,6 +46,9 @@ public class CodegenConstants {
public static final String SORT_PARAMS_BY_REQUIRED_FLAG = "sortParamsByRequiredFlag";
public static final String SORT_PARAMS_BY_REQUIRED_FLAG_DESC = "Sort method arguments to place required parameters before optional parameters.";
public static final String USE_DATETIME_OFFSET = "useDateTimeOffset";
public static final String USE_DATETIME_OFFSET_DESC = "Use DateTimeOffset to model date-time properties";
public static final String ENSURE_UNIQUE_PARAMS = "ensureUniqueParams";
public static final String ENSURE_UNIQUE_PARAMS_DESC = "Whether to ensure parameter names are unique in an operation (rename parameters that are not).";
@ -54,4 +57,50 @@ public class CodegenConstants {
public static final String POD_VERSION = "podVersion";
public static final String OPTIONAL_METHOD_ARGUMENT = "optionalMethodArgument";
public static final String OPTIONAL_METHOD_ARGUMENT_DESC = "Optional method argument, e.g. void square(int x=10) (.net 4.0+ only).";
public static final String OPTIONAL_ASSEMBLY_INFO = "optionalAssemblyInfo";
public static final String OPTIONAL_ASSEMBLY_INFO_DESC = "Generate AssemblyInfo.cs.";
public static final String USE_COLLECTION = "useCollection";
public static final String USE_COLLECTION_DESC = "Deserialize array types to Collection<T> instead of List<T>.";
public static final String RETURN_ICOLLECTION = "returnICollection";
public static final String RETURN_ICOLLECTION_DESC = "Return ICollection<T> instead of the concrete type.";
public static final String OPTIONAL_PROJECT_FILE = "optionalProjectFile";
public static final String OPTIONAL_PROJECT_FILE_DESC = "Generate {PackageName}.csproj.";
public static final String OPTIONAL_PROJECT_GUID = "packageGuid";
public static final String OPTIONAL_PROJECT_GUID_DESC = "The GUID that will be associated with the C# project";
public static final String MODEL_PROPERTY_NAMING = "modelPropertyNaming";
public static final String MODEL_PROPERTY_NAMING_DESC = "Naming convention for the property: 'camelCase', 'PascalCase', 'snake_case' and 'original', which keeps the original name";
public static final String DOTNET_FRAMEWORK = "targetFramework";
public static final String DOTNET_FRAMEWORK_DESC = "The target .NET framework version.";
public static enum MODEL_PROPERTY_NAMING_TYPE {camelCase, PascalCase, snake_case, original}
public static final String MODEL_NAME_PREFIX = "modelNamePrefix";
public static final String MODEL_NAME_PREFIX_DESC = "Prefix that will be prepended to all model names. Default is the empty string.";
public static final String MODEL_NAME_SUFFIX = "modelNameSuffix";
public static final String MODEL_NAME_SUFFIX_DESC = "Suffix that will be appended to all model names. Default is the empty string.";
public static final String OPTIONAL_EMIT_DEFAULT_VALUES = "optionalEmitDefaultValues";
public static final String OPTIONAL_EMIT_DEFAULT_VALUES_DESC = "Set DataMember's EmitDefaultValue, default false.";
public static final String GIT_USER_ID = "gitUserId";
public static final String GIT_USER_ID_DESC = "Git user ID, e.g. swagger-api.";
public static final String GIT_REPO_ID = "gitRepoId";
public static final String GIT_REPO_ID_DESC = "Git repo ID, e.g. swagger-codegen.";
public static final String RELEASE_NOTE = "releaseNote";
public static final String RELEASE_NOTE_DESC = "Release note, default to 'Minor update'.";
public static final String HTTP_USER_AGENT = "httpUserAgent";
public static final String HTTP_USER_AGENT_DESC = "HTTP user agent, e.g. codegen_csharp_api_client, default to 'Swagger-Codegen/{packageVersion}}/{language}'";
}

View File

@ -6,18 +6,35 @@ import java.util.*;
public class CodegenModel {
public String parent, parentSchema;
public List<String> interfaces;
// References to parent and interface CodegenModels. Only set when code generator supports inheritance.
public CodegenModel parentModel;
public List<CodegenModel> interfaceModels;
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 discriminator;
public String defaultValue;
public List<CodegenProperty> vars = new ArrayList<CodegenProperty>();
public List<CodegenProperty> allVars;
public List<String> allowableValues;
// list of all required parameters
public Set<String> mandatory = new HashSet<String>();
// Sorted sets of required parameters.
public Set<String> mandatory = new TreeSet<String>();
public Set<String> allMandatory;
public Set<String> imports = new TreeSet<String>();
public Boolean hasVars, emptyVars, hasMoreModels, hasEnums, isEnum;
public ExternalDocs externalDocs;
public Map<String, Object> vendorExtensions;
{
// By default these are the same collections. Where the code generator supports inheritance, composed models
// store the complete closure of owned and inherited properties in allVars and allMandatory.
allVars = vars;
allMandatory = mandatory;
}
}

View File

@ -15,7 +15,7 @@ public class CodegenOperation {
isListContainer, isMultipart, hasMore = Boolean.TRUE,
isResponseBinary = Boolean.FALSE, hasReference = Boolean.FALSE;
public String path, operationId, returnType, httpMethod, returnBaseType,
returnContainer, summary, notes, baseName, defaultResponse;
returnContainer, summary, notes, baseName, defaultResponse, discriminator;
public List<Map<String, String>> consumes, produces;
public CodegenParameter bodyParam;
public List<CodegenParameter> allParams = new ArrayList<CodegenParameter>();
@ -32,13 +32,14 @@ public class CodegenOperation {
public ExternalDocs externalDocs;
public Map<String, Object> vendorExtensions;
public String nickname; // legacy support
public String operationIdLowerCase; // for mardown documentation
/**
* Check if there's at least one parameter
*
* @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;
}

View File

@ -7,13 +7,18 @@ import java.util.List;
public class CodegenParameter {
public Boolean isFormParam, isQueryParam, isPathParam, isHeaderParam,
isCookieParam, isBodyParam, isFile, notFile, hasMore, isContainer,
secondaryParam, isBinary, isCollectionFormatMulti;
public String baseName, paramName, dataType, collectionFormat, description, baseType, defaultValue;
isCookieParam, isBodyParam, hasMore, isContainer,
secondaryParam, isCollectionFormatMulti, isPrimitiveType;
public String baseName, paramName, dataType, datatypeWithEnum, collectionFormat, description, baseType, defaultValue;
public String example; // example value (x-example)
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 List<String> _enum;
public Map<String, Object> allowableValues;
public CodegenProperty items;
public Map<String, Object> vendorExtensions;
/**
@ -78,6 +83,7 @@ public class CodegenParameter {
output.baseName = this.baseName;
output.paramName = this.paramName;
output.dataType = this.dataType;
output.datatypeWithEnum = this.datatypeWithEnum;
output.collectionFormat = this.collectionFormat;
output.isCollectionFormatMulti = this.isCollectionFormatMulti;
output.description = this.description;
@ -102,6 +108,7 @@ public class CodegenParameter {
output.multipleOf = this.multipleOf;
output.jsonSchema = this.jsonSchema;
output.defaultValue = this.defaultValue;
output.example = this.example;
output.isEnum = this.isEnum;
if (this._enum != null) {
output._enum = new ArrayList<String>(this._enum);
@ -109,7 +116,22 @@ public class CodegenParameter {
if (this.allowableValues != null) {
output.allowableValues = new HashMap<String, Object>(this.allowableValues);
}
if (this.items != null) {
output.items = this.items;
}
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;
}

View File

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

View File

@ -8,6 +8,7 @@ import io.swagger.models.auth.SecuritySchemeDefinition;
import io.swagger.models.parameters.Parameter;
import io.swagger.util.Json;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -15,11 +16,10 @@ import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.*;
import static org.apache.commons.lang3.StringUtils.capitalize;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
public class DefaultGenerator extends AbstractGenerator implements Generator {
Logger LOGGER = LoggerFactory.getLogger(DefaultGenerator.class);
protected Logger LOGGER = LoggerFactory.getLogger(DefaultGenerator.class);
protected CodegenConfig config;
protected ClientOptInput opts;
@ -129,6 +129,13 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
if (info.getVersion() != null) {
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();
@ -161,22 +168,63 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
List<Object> allModels = new ArrayList<Object>();
// models
Map<String, Model> definitions = swagger.getDefinitions();
final Map<String, Model> definitions = swagger.getDefinitions();
if (definitions != null) {
List<String> sortedModelKeys = sortModelsByInheritance(definitions);
Set<String> modelKeys = definitions.keySet();
if(generateModels) {
if(modelsToGenerate != null && modelsToGenerate.size() > 0) {
List<String> updatedKeys = new ArrayList<String>();
for(String m : sortedModelKeys) {
Set<String> updatedKeys = new HashSet<String>();
for(String m : modelKeys) {
if(modelsToGenerate.contains(m)) {
updatedKeys.add(m);
}
}
sortedModelKeys = updatedKeys;
modelKeys = updatedKeys;
}
for (String name : sortedModelKeys) {
// store all processed models
Map<String,Object> allProcessedModels = new TreeMap<String, Object>(new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
Model model1 = definitions.get(o1);
Model model2 = definitions.get(o2);
int model1InheritanceDepth = getInheritanceDepth(model1);
int model2InheritanceDepth = getInheritanceDepth(model2);
if (model1InheritanceDepth == model2InheritanceDepth) {
return ObjectUtils.compare(config.toModelName(o1), config.toModelName(o2));
} else if (model1InheritanceDepth > model2InheritanceDepth) {
return 1;
} else {
return -1;
}
}
private int getInheritanceDepth(Model model) {
int inheritanceDepth = 0;
Model parent = getParent(model);
while (parent != null) {
inheritanceDepth++;
parent = getParent(parent);
}
return inheritanceDepth;
}
private Model getParent(Model model) {
if (model instanceof ComposedModel) {
return definitions.get(((ComposedModel) model).getParent().getReference());
}
return null;
}
});
// process models only
for (String name : modelKeys) {
try {
//don't generate models that have an import mapping
if(config.importMapping().containsKey(name)) {
@ -187,8 +235,29 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
Map<String, Model> modelMap = new HashMap<String, Model>();
modelMap.put(name, model);
Map<String, Object> models = processModels(config, modelMap, definitions);
models.put("classname", config.toModelName(name));
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));
for (String templateName : config.modelTemplateFiles().keySet()) {
@ -211,6 +280,50 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
writeToFile(filename, tmpl.execute(models));
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));
}
// to generate model documentation files
for (String templateName : config.modelDocTemplateFiles().keySet()) {
String suffix = config.modelDocTemplateFiles().get(templateName);
String filename = config.modelDocFileFolder() + File.separator + config.toModelDocFilename(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) {
throw new RuntimeException("Could not generate model '" + name + "'", e);
}
@ -218,7 +331,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
}
if (System.getProperty("debugModels") != null) {
System.out.println("############ Model info ############");
LOGGER.info("############ Model info ############");
Json.prettyPrint(allModels);
}
@ -237,6 +350,12 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
for (String tag : paths.keySet()) {
try {
List<CodegenOperation> ops = paths.get(tag);
Collections.sort(ops, new Comparator<CodegenOperation>() {
@Override
public int compare(CodegenOperation one, CodegenOperation another) {
return ObjectUtils.compare(one.operationId, another.operationId);
}
});
Map<String, Object> operation = processOperations(config, tag, ops);
operation.put("basePath", basePath);
@ -249,6 +368,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
operation.put("classVarName", config.toApiVarName(tag));
operation.put("importPath", config.toApiImport(tag));
if(!config.vendorExtensions().isEmpty()) {
operation.put("vendorExtensions", config.vendorExtensions());
}
// Pass sortParamsByRequiredFlag through to the Mustache template...
boolean sortParamsByRequiredFlag = true;
if (this.config.additionalProperties().containsKey(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG)) {
@ -288,13 +411,61 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
writeToFile(filename, tmpl.execute(operation));
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));
}
// to generate api documentation files
for (String templateName : config.apiDocTemplateFiles().keySet()) {
String filename = config.apiDocFilename(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) {
throw new RuntimeException("Could not generate api file for '" + tag + "'", e);
}
}
}
if (System.getProperty("debugOperations") != null) {
System.out.println("############ Operation info ############");
LOGGER.info("############ Operation info ############");
Json.prettyPrint(allOperations);
}
@ -333,7 +504,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
config.postProcessSupportingFileData(bundle);
if (System.getProperty("debugSupportingFiles") != null) {
System.out.println("############ Supporting file info ############");
LOGGER.info("############ Supporting file info ############");
Json.prettyPrint(bundle);
}
@ -392,18 +563,14 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
File outputFile = new File(outputFilename);
OutputStream out = new FileOutputStream(outputFile, false);
if (in != null && out != null) {
System.out.println("writing file " + outputFile);
if (in != null) {
LOGGER.info("writing file " + outputFile);
IOUtils.copy(in, out);
} else {
if (in == null) {
System.out.println("can't open " + templateFile + " for input");
}
if (out == null) {
System.out.println("can't open " + outputFile + " for output");
LOGGER.error("can't open " + templateFile + " for input");
}
}
files.add(outputFile);
}
}
@ -412,13 +579,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
}
}
config.processSwagger(swagger);
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) {
List<Map<String, String>> c = new ArrayList<Map<String, String>>();
int count = 0;
@ -439,54 +604,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
}
private List<String> sortModelsByInheritance(final Map<String, Model> definitions) {
List<String> sortedModelKeys = new ArrayList<String>(definitions.keySet());
Comparator<String> cmp = new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
Model model1 = definitions.get(o1);
Model model2 = definitions.get(o2);
int model1InheritanceDepth = getInheritanceDepth(model1);
int model2InheritanceDepth = getInheritanceDepth(model2);
if (model1InheritanceDepth == model2InheritanceDepth) {
return 0;
} else if (model1InheritanceDepth > model2InheritanceDepth) {
return 1;
} else {
return -1;
}
}
private int getInheritanceDepth(Model model) {
int inheritanceDepth = 0;
Model parent = getParent(model);
while (parent != null) {
inheritanceDepth++;
parent = getParent(parent);
}
return inheritanceDepth;
}
private Model getParent(Model model) {
if (model instanceof ComposedModel) {
return definitions.get(((ComposedModel) model).getParent().getReference());
}
return null;
}
};
Collections.sort(sortedModelKeys, cmp);
return sortedModelKeys;
}
public Map<String, List<CodegenOperation>> processPaths(Map<String, Path> paths) {
Map<String, List<CodegenOperation>> ops = new HashMap<String, List<CodegenOperation>>();
Map<String, List<CodegenOperation>> ops = new TreeMap<String, List<CodegenOperation>>();
for (String resourcePath : paths.keySet()) {
Path path = paths.get(resourcePath);
@ -512,7 +631,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
public void processOperation(String resourcePath, String httpMethod, Operation operation, Map<String, List<CodegenOperation>> operations, Path path) {
if (operation != 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();
if (tags == null) {
@ -547,8 +667,8 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
try {
co = config.fromOperation(resourcePath, httpMethod, operation, swagger.getDefinitions(), swagger);
co.tags = new ArrayList<String>();
co.tags.add(sanitizeTag(tag));
config.addOperationToGroup(sanitizeTag(tag), resourcePath, operation, co, operations);
co.tags.add(config.sanitizeTag(tag));
config.addOperationToGroup(config.sanitizeTag(tag), resourcePath, operation, co, operations);
List<Map<String, List<String>>> securities = operation.getSecurity();
if (securities == null && swagger.getSecurity() != null) {
@ -561,14 +681,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
continue;
}
Map<String, SecuritySchemeDefinition> authMethods = new HashMap<String, SecuritySchemeDefinition>();
// NOTE: Use only the first security requirement for now.
// See the "security" field of "Swagger Object":
// https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#swagger-object
// "there is a logical OR between the security requirements"
if (securities.size() > 1) {
LOGGER.warn("More than 1 security requirements are found, using only the first one");
}
Map<String, List<String>> security = securities.get(0);
for (Map<String, List<String>> security: securities) {
for (String securityName : security.keySet()) {
SecuritySchemeDefinition securityDefinition = fromSecurity(securityName);
if (securityDefinition != null) {
@ -591,6 +704,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
}
}
}
if (!authMethods.isEmpty()) {
co.authMethods = config.fromSecurity(authMethods);
co.hasAuthMethods = true;
@ -609,22 +723,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
}
}
private String generateParameterId(Parameter parameter) {
private static String generateParameterId(Parameter parameter) {
return parameter.getName() + ":" + parameter.getIn();
}
protected String sanitizeTag(String tag) {
// 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 ]", "");
}
@SuppressWarnings("static-method")
public Map<String, Object> processOperations(CodegenConfig config, String tag, List<CodegenOperation> ops) {
Map<String, Object> operations = new HashMap<String, Object>();
Map<String, Object> objs = new HashMap<String, Object>();
@ -685,6 +788,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
return operations;
}
@SuppressWarnings("static-method")
public Map<String, Object> processModels(CodegenConfig config, Map<String, Model> definitions, Map<String, Model> allDefinitions) {
Map<String, Object> objs = new HashMap<String, Object>();
objs.put("package", config.modelPackage());
@ -695,7 +799,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
CodegenModel cm = config.fromModel(key, mm, allDefinitions);
Map<String, Object> mo = new HashMap<String, Object>();
mo.put("model", cm);
mo.put("importPath", config.toModelImport(key));
mo.put("importPath", config.toModelImport(cm.classname));
models.add(mo);
allImports.addAll(cm.imports);
@ -704,7 +808,6 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
Set<String> importSet = new TreeSet<String>();
for (String nextImport : allImports) {
Map<String, String> im = new HashMap<String, String>();
String mapping = config.importMapping().get(nextImport);
if (mapping == null) {
mapping = config.toModelImport(nextImport);

View File

@ -1,21 +1,18 @@
package io.swagger.codegen;
import com.sun.org.apache.xpath.internal.operations.Mod;
import io.swagger.models.*;
import io.swagger.models.parameters.BodyParameter;
import io.swagger.models.parameters.Parameter;
import io.swagger.models.parameters.RefParameter;
import io.swagger.models.properties.*;
import io.swagger.util.Json;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class InlineModelResolver {
private Swagger swagger;
private boolean skipMatches;
@ -51,23 +48,24 @@ public class InlineModelResolver {
if(model instanceof ModelImpl) {
ModelImpl obj = (ModelImpl) model;
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);
String modelName = uniqueName(bp.getName());
bp.setSchema(new RefModel(modelName));
addGenerated(modelName, model);
swagger.addDefinition(modelName, model);
}
}
}
else if (model instanceof ArrayModel) {
ArrayModel am = (ArrayModel) model;
Property inner = am.getItems();
if(inner instanceof ObjectProperty) {
String modelName = uniqueName(bp.getName());
ObjectProperty op = (ObjectProperty) inner;
if (op.getProperties() != null && op.getProperties().size() > 0) {
flattenProperties(op.getProperties(), pathname);
String modelName = uniqueName(bp.getName());
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
@ -83,6 +81,7 @@ public class InlineModelResolver {
}
}
}
}
Map<String, Response> responses = operation.getResponses();
if (responses != null) {
for (String key : responses.keySet()) {
@ -90,8 +89,9 @@ public class InlineModelResolver {
if (response.getSchema() != null) {
Property property = response.getSchema();
if (property instanceof ObjectProperty) {
String modelName = uniqueName("inline_response_" + key);
ObjectProperty op = (ObjectProperty) property;
if (op.getProperties() != null && op.getProperties().size() > 0) {
String modelName = uniqueName("inline_response_" + key);
Model model = modelFromProperty(op, modelName);
String existing = matchGenerated(model);
if (existing != null) {
@ -101,15 +101,16 @@ public class InlineModelResolver {
addGenerated(modelName, model);
swagger.addDefinition(modelName, model);
}
}
} else if (property instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) property;
Property inner = ap.getItems();
if(inner instanceof ObjectProperty) {
String modelName = uniqueName("inline_response_" + key);
ObjectProperty op = (ObjectProperty) inner;
if (op.getProperties() != null && op.getProperties().size() > 0) {
flattenProperties(op.getProperties(), pathname);
String modelName = uniqueName("inline_response_" + key);
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
@ -120,15 +121,16 @@ public class InlineModelResolver {
swagger.addDefinition(modelName, innerModel);
}
}
}
} else if (property instanceof MapProperty) {
MapProperty mp = (MapProperty) property;
Property innerProperty = mp.getAdditionalProperties();
if(innerProperty instanceof ObjectProperty) {
String modelName = uniqueName("inline_response_" + key);
ObjectProperty op = (ObjectProperty) innerProperty;
if (op.getProperties() != null && op.getProperties().size() > 0) {
flattenProperties(op.getProperties(), pathname);
String modelName = uniqueName("inline_response_" + key);
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
@ -146,6 +148,7 @@ public class InlineModelResolver {
}
}
}
}
// definitions
if (models != null) {
@ -162,9 +165,10 @@ public class InlineModelResolver {
ArrayModel m = (ArrayModel) model;
Property inner = m.getItems();
if (inner instanceof ObjectProperty) {
ObjectProperty op = (ObjectProperty) inner;
if (op.getProperties() != null && op.getProperties().size() > 0) {
String innerModelName = uniqueName(modelName + "_inner");
Model innerModel = modelFromProperty((ObjectProperty) inner, modelName);
Model innerModel = modelFromProperty(op, innerModelName);
String existing = matchGenerated(innerModel);
if (existing == null) {
swagger.addDefinition(innerModelName, innerModel);
@ -174,8 +178,7 @@ public class InlineModelResolver {
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) {
int count = 0;
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) {
String name = key;
if (count > 0) {
@ -223,7 +226,9 @@ public class InlineModelResolver {
Map<String, Model> modelsToAdd = new HashMap<String, Model>();
for (String key : properties.keySet()) {
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);
ObjectProperty op = (ObjectProperty) property;
@ -244,14 +249,12 @@ public class InlineModelResolver {
Property inner = ap.getItems();
if (inner instanceof ObjectProperty) {
String modelName = uniqueName(path + "_" + key);
ObjectProperty op = (ObjectProperty) inner;
if (op.getProperties() != null && op.getProperties().size() > 0) {
flattenProperties(op.getProperties(), path);
String modelName = uniqueName(path + "_" + key);
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
ap.setItems(new RefProperty(existing));
} else {
@ -260,19 +263,18 @@ public class InlineModelResolver {
swagger.addDefinition(modelName, innerModel);
}
}
}
} else if (property instanceof MapProperty) {
MapProperty mp = (MapProperty) property;
Property inner = mp.getAdditionalProperties();
if (inner instanceof ObjectProperty) {
String modelName = uniqueName(path + "_" + key);
ObjectProperty op = (ObjectProperty) inner;
if (op.getProperties() != null && op.getProperties().size() > 0) {
flattenProperties(op.getProperties(), path);
String modelName = uniqueName(path + "_" + key);
Model innerModel = modelFromProperty(op, modelName);
String existing = matchGenerated(innerModel);
if (existing != null) {
mp.setAdditionalProperties(new RefProperty(existing));
} else {
@ -281,7 +283,7 @@ public class InlineModelResolver {
swagger.addDefinition(modelName, innerModel);
}
}
} else {
}
}
}
if (propsToUpdate.size() > 0) {
@ -295,53 +297,36 @@ public class InlineModelResolver {
}
}
public Model modelFromProperty(ArrayProperty object, String path) {
String access = object.getAccess();
@SuppressWarnings("static-method")
public Model modelFromProperty(ArrayProperty object, @SuppressWarnings("unused") String path) {
String description = object.getDescription();
String example = object.getExample();
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();
String example = null;
Object obj = object.getExample();
if(obj != null) {
example = obj.toString();
}
Property inner = object.getItems();
if (inner instanceof ObjectProperty) {
ArrayModel model = new ArrayModel();
model.setDescription(description);
model.setExample(example);
// model.setName(name);
// model.setXml(xml);
model.setItems(object.getItems());
return model;
}
// if(properties != null) {
// flattenProperties(properties, path);
// model.setProperties(properties);
// }
return null;
}
public Model modelFromProperty(ObjectProperty object, String path) {
String access = object.getAccess();
String description = object.getDescription();
String example = object.getExample();
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();
String example = null;
Object obj = object.getExample();
if(obj != null) {
example = obj.toString();
}
String name = object.getName();
Xml xml = object.getXml();
Map<String, Property> properties = object.getProperties();
ModelImpl model = new ModelImpl();
@ -358,17 +343,15 @@ public class InlineModelResolver {
return model;
}
public Model modelFromProperty(MapProperty object, String path) {
String access = object.getAccess();
@SuppressWarnings("static-method")
public Model modelFromProperty(MapProperty object, @SuppressWarnings("unused") String path) {
String description = object.getDescription();
String example = object.getExample();
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();
String example = null;
Object obj = object.getExample();
if(obj != null) {
example = obj.toString();
}
ArrayModel model = new ArrayModel();
model.setDescription(description);

View File

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

View File

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

View File

@ -7,10 +7,17 @@ import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import config.ConfigParser;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
public class AuthParser {
private static final Logger LOGGER = LoggerFactory.getLogger(AuthParser.class);
public static List<AuthorizationValue> parse(String urlEncodedAuthStr) {
List<AuthorizationValue> auths = new ArrayList<AuthorizationValue>();
if (isNotEmpty(urlEncodedAuthStr)) {
@ -18,7 +25,7 @@ public class AuthParser {
for (String part : parts) {
String[] kvPair = part.split(":");
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"));
} catch (Exception e) {
// continue
e.printStackTrace();
LOGGER.error(e.getMessage(), e);
}
}
return b.toString();

View File

@ -36,7 +36,7 @@ import static org.apache.commons.lang3.StringUtils.isNotEmpty;
*/
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 inputSpec;
@ -48,6 +48,8 @@ public class CodegenConfigurator {
private String apiPackage;
private String modelPackage;
private String invokerPackage;
private String modelNamePrefix;
private String modelNameSuffix;
private String groupId;
private String artifactId;
private String artifactVersion;
@ -58,6 +60,10 @@ public class CodegenConfigurator {
private Map<String, String> additionalProperties = new HashMap<String, String>();
private Map<String, String> importMappings = new HashMap<String, String>();
private Set<String> languageSpecificPrimitives = new HashSet<String>();
private String gitUserId="YOUR_GIT_USR_ID";
private String gitRepoId="YOUR_GIT_REPO_ID";
private String releaseNote="Minor update";
private String httpUserAgent;
private final Map<String, String> dynamicProperties = new HashMap<String, String>(); //the map that holds the JsonAnySetter/JsonAnyGetter values
@ -97,6 +103,24 @@ public class CodegenConfigurator {
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() {
return verbose;
}
@ -275,6 +299,42 @@ public class CodegenConfigurator {
return this;
}
public String getGitUserId() {
return gitUserId;
}
public CodegenConfigurator setGitUserId(String gitUserId) {
this.gitUserId = gitUserId;
return this;
}
public String getGitRepoId() {
return gitRepoId;
}
public CodegenConfigurator setGitRepoId(String gitRepoId) {
this.gitRepoId = gitRepoId;
return this;
}
public String getReleaseNote() {
return releaseNote;
}
public CodegenConfigurator setReleaseNote(String releaseNote) {
this.releaseNote = releaseNote;
return this;
}
public String getHttpUserAgent() {
return httpUserAgent;
}
public CodegenConfigurator setHttpUserAgent(String httpUserAgent) {
this.httpUserAgent= httpUserAgent;
return this;
}
public ClientOptInput toClientOptInput() {
Validate.notEmpty(lang, "language must be specified");
@ -300,6 +360,12 @@ public class CodegenConfigurator {
checkAndSetAdditionalProperty(artifactId, CodegenConstants.ARTIFACT_ID);
checkAndSetAdditionalProperty(artifactVersion, CodegenConstants.ARTIFACT_VERSION);
checkAndSetAdditionalProperty(templateDir, toAbsolutePathStr(templateDir), CodegenConstants.TEMPLATE_DIR);
checkAndSetAdditionalProperty(modelNamePrefix, CodegenConstants.MODEL_NAME_PREFIX);
checkAndSetAdditionalProperty(modelNameSuffix, CodegenConstants.MODEL_NAME_SUFFIX);
checkAndSetAdditionalProperty(gitUserId, CodegenConstants.GIT_USER_ID);
checkAndSetAdditionalProperty(gitRepoId, CodegenConstants.GIT_REPO_ID);
checkAndSetAdditionalProperty(releaseNote, CodegenConstants.RELEASE_NOTE);
checkAndSetAdditionalProperty(httpUserAgent, CodegenConstants.HTTP_USER_AGENT);
handleDynamicProperties(config);
@ -349,7 +415,7 @@ public class CodegenConfigurator {
if (!verbose) {
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 - [debugModels] prints models passed to the template engine" +
"\n - [debugOperations] prints operations passed to the template engine" +
@ -392,7 +458,7 @@ public class CodegenConfigurator {
try {
return Json.mapper().readValue(new File(configFile), CodegenConfigurator.class);
} catch (IOException e) {
LOG.error("Unable to deserialize config file: " + configFile, e);
LOGGER.error("Unable to deserialize config file: " + configFile, e);
}
}
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 (mediaTypes == null) {
// 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) {
Map<String, String> kv = new HashMap<String, String>();
@ -93,9 +93,9 @@ public class ExampleGenerator {
};
}
} 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) {
return new java.util.Date(System.currentTimeMillis());
return "2000-01-23T04:56:07.000+0000";
} else if (property instanceof DecimalProperty) {
return new BigDecimal(1.3579);
} else if (property instanceof DoubleProperty) {
@ -142,16 +142,14 @@ public class ExampleGenerator {
ModelImpl impl = (ModelImpl) model;
Map<String, Object> values = new HashMap<String, Object>();
if (impl != null && impl.getProperties() != null) {
if (impl.getProperties() != null) {
for (String propertyName : impl.getProperties().keySet()) {
Property property = impl.getProperties().get(propertyName);
values.put(propertyName, resolvePropertyToExample(mediaType, property, processedModels));
}
}
return values;
}
return "";
}
}

View File

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

View File

@ -0,0 +1,546 @@
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 String.format("%1$sF", dp.getDefault());
}
} 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)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (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,192 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenParameter;
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 ) {
boolean isMultipartPost = false;
List<Map<String, String>> consumes = operation.consumes;
if(consumes != null) {
for(Map<String, String> consume : consumes) {
String mt = consume.get("mediaType");
if(mt != null) {
if(mt.startsWith("multipart/form-data")) {
isMultipartPost = true;
}
}
}
}
for(CodegenParameter parameter : operation.allParams) {
if(isMultipartPost) {
parameter.vendorExtensions.put("x-multipart", "true");
}
}
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;
public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
}
protected String modelPropertyNaming= "camelCase";
public AbstractTypeScriptClientCodegen() {
super();
supportsInheritance = true;
reservedWords = new HashSet<String>(Arrays.asList(
setReservedWordsLowerCase(Arrays.asList(
// local variable names used in API methods (endpoints)
"path", "queryParameters", "headerParams", "formParams", "useFormData", "deferred",
"varLocalPath", "queryParameters", "headerParams", "formParams", "useFormData", "varLocalDeferred",
"requestOptions",
// Typescript reserved words
"abstract", "await", "boolean", "break", "byte", "case", "catch", "char", "class", "const", "continue", "debugger", "default", "delete", "do", "double", "else", "enum", "export", "extends", "false", "final", "finally", "float", "for", "function", "goto", "if", "implements", "import", "in", "instanceof", "int", "interface", "let", "long", "native", "new", "null", "package", "private", "protected", "public", "return", "short", "static", "super", "switch", "synchronized", "this", "throw", "transient", "true", "try", "typeof", "var", "void", "volatile", "while", "with", "yield"));
languageSpecificPrimitives = new HashSet<String>(Arrays.asList(
"string",
"String",
"boolean",
"Boolean",
@ -32,7 +31,12 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
"Integer",
"Long",
"Float",
"Object"));
"Object",
"Array",
"Date",
"number",
"any"
));
instantiationTypes.put("array", "Array");
typeMapping = new HashMap<String, String>();
@ -52,7 +56,27 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
typeMapping.put("integer", "number");
typeMapping.put("Map", "any");
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
@ -71,9 +95,9 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
}
@Override
public String toVarName(String name) {
public String toParamName(String name) {
// 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 (name.matches("^[A-Z_]*$"))
@ -84,24 +108,43 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
name = camelize(name, true);
// 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);
return name;
}
@Override
public String toParamName(String name) {
public String toVarName(String name) {
// should be the same as variable name
return toVarName(name);
return getNameUsingModelPropertyNaming(name);
}
@Override
public String toModelName(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
if (reservedWords.contains(name))
throw new RuntimeException(name
+ " (reserved word) cannot be used as a model name");
if (isReservedWord(name)) {
String modelName = camelize("model_" + name);
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
// model name starts with number
if (name.matches("^\\d.*")) {
String modelName = camelize("model_" + name); // e.g. 200Response => Model200Response (after camelize)
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
// camelize the model name
// phone_number => PhoneNumber
@ -140,7 +183,7 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
return type;
} else
type = swaggerType;
return type;
return toModelName(type);
}
@Override
@ -152,10 +195,38 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
// method name cannot use reserved keyword, e.g. return
// append _ at the beginning, e.g. _return
if (reservedWords.contains(operationId)) {
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.
*/
protected boolean onlyOneSuccess = true;
Logger LOGGER = LoggerFactory.getLogger(AkkaScalaClientCodegen.class);
@SuppressWarnings("hiding")
protected Logger LOGGER = LoggerFactory.getLogger(AkkaScalaClientCodegen.class);
public AkkaScalaClientCodegen() {
super();
@ -74,7 +76,7 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
apiPackage = mainPackage + ".api";
modelPackage = mainPackage + ".model";
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
"abstract", "case", "catch", "class", "def", "do", "else", "extends",
"false", "final", "finally", "for", "forSome", "if", "implicit",
@ -274,7 +276,7 @@ public class AkkaScalaClientCodegen extends DefaultCodegen implements CodegenCon
if (capitalized) {
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 escapeReservedWord(identifier);

View File

@ -7,7 +7,6 @@ import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
@ -16,8 +15,11 @@ import java.util.Arrays;
import java.util.HashSet;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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";
protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger";
@ -40,8 +42,14 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
// local variable names used in API methods (endpoints)
"localVarPostBody", "localVarPath", "localVarQueryParams", "localVarHeaderParams",
"localVarFormParams", "localVarContentTypes", "localVarContentType",
"localVarResponse", "localVarBuilder", "authNames", "basePath", "apiInvoker",
// android reserved words
"abstract", "continue", "for", "new", "switch", "assert",
"default", "if", "package", "synchronized", "boolean", "do", "goto", "private",
"this", "break", "double", "implements", "protected", "throw", "byte", "else",
@ -60,10 +68,13 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
"Integer",
"Long",
"Float",
"byte[]",
"Object")
);
instantiationTypes.put("array", "ArrayList");
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.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
@ -133,8 +144,10 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type)) {
return toModelName(type);
if (languageSpecificPrimitives.contains(type) || type.indexOf(".") >= 0 ||
type.equals("Map") || type.equals("List") ||
type.equals("File") || type.equals("Date")) {
return type;
}
} else {
type = swaggerType;
@ -144,8 +157,11 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
// 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 (name.matches("^[A-Z_]*$")) {
@ -157,7 +173,7 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
name = camelize(name, true);
// 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);
}
@ -172,14 +188,34 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
@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");
// add prefix, suffix if needed
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// camelize the model name
// 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;
}
// model name starts with number
if (name.matches("^\\d.*")) {
String modelName = "Model" + name; // e.g. 200Response => Model200Response (after camelize)
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return name;
}
@Override
@ -195,12 +231,16 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
throw new RuntimeException("Empty method name (operationId) not allowed");
}
operationId = camelize(sanitizeName(operationId), true);
// 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");
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;
}
return camelize(operationId, true);
return operationId;
}
@Override
@ -272,6 +312,8 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiException.java"));
supportingFiles.add(new SupportingFile("Pair.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "Pair.java"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
}
private void addSupportingFilesForVolley() {
@ -281,10 +323,6 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "ApiInvoker.java"));
supportingFiles.add(new SupportingFile("responses.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "Responses.java"));
// supportingFiles.add(new SupportingFile("httpPatch.mustache",
// (sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "HttpPatch.java"));
supportingFiles.add(new SupportingFile("jsonUtil.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", File.separator), "JsonUtil.java"));
supportingFiles.add(new SupportingFile("apiException.mustache",

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.HashSet;
import org.apache.commons.lang.StringUtils;
public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.client";
protected String groupId = "io.swagger";
@ -45,8 +43,13 @@ public class AsyncScalaClientCodegen extends DefaultCodegen implements CodegenCo
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
// local variable names used in API methods (endpoints)
"config", "path", "contentTypes", "contentType", "queryParams", "headerParams",
"formParams", "postBody", "resFuture", "client", "reader",
// scala reserved words
"abstract", "case", "catch", "class", "def", "do", "else", "extends",
"false", "final", "finally", "for", "forSome", "if", "implicit",
"import", "lazy", "match", "new", "null", "object", "override", "package",

View File

@ -1,14 +1,19 @@
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.CodegenConstants;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.models.properties.*;
import io.swagger.codegen.CliOption;
import io.swagger.models.Model;
import java.io.File;
import java.util.Arrays;
@ -16,121 +21,120 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.WordUtils;
import org.slf4j.Logger;
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);
protected boolean optionalMethodArgumentFlag = true;
private static final String NET45 = "v4.5";
private static final String NET35 = "v3.5";
private static final String DATA_TYPE_WITH_ENUM_EXTENSION = "plainDatatypeWithEnum";
protected String packageGuid = "{" + java.util.UUID.randomUUID().toString().toUpperCase() + "}";
protected String packageTitle = "Swagger Library";
protected String packageProductName = "SwaggerLibrary";
protected String packageDescription = "A library generated from a Swagger doc";
protected String packageCompany = "Swagger";
protected String packageCopyright = "No Copyright";
protected String packageName = "IO.Swagger";
protected String packageVersion = "1.0.0";
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() {
super();
outputFolder = "generated-code" + File.separator + "csharp";
modelTemplateFiles.put("model.mustache", ".cs");
apiTemplateFiles.put("api.mustache", ".cs");
embeddedTemplateDir = templateDir = "csharp";
apiPackage = "IO.Swagger.Api";
modelPackage = "IO.Swagger.Model";
reservedWords = new HashSet<String>(
Arrays.asList(
// 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")
);
modelTestTemplateFiles.put("model_test.mustache", ".cs");
apiTestTemplateFiles.put("api_test.mustache", ".cs");
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
"string",
"bool?",
"double?",
"int?",
"long?",
"float?",
"byte[]",
"List",
"Dictionary",
"DateTime?",
"String",
"Boolean",
"Double",
"Integer",
"Long",
"Float",
"Stream", // not really a primitive, we include it to avoid model import
"Object")
);
instantiationTypes.put("array", "List");
instantiationTypes.put("map", "Dictionary");
typeMapping = new HashMap<String, String>();
typeMapping.put("string", "string");
typeMapping.put("boolean", "bool?");
typeMapping.put("integer", "int?");
typeMapping.put("float", "float?");
typeMapping.put("long", "long?");
typeMapping.put("double", "double?");
typeMapping.put("number", "double?");
typeMapping.put("datetime", "DateTime?");
typeMapping.put("date", "DateTime?");
typeMapping.put("file", "Stream");
typeMapping.put("array", "List");
typeMapping.put("list", "List");
typeMapping.put("map", "Dictionary");
typeMapping.put("object", "Object");
// C# client default
setSourceFolder("src" + File.separator + "main" + File.separator + "csharp");
cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "C# package name (convention: Camel.Case).")
.defaultValue("IO.Swagger"));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "C# package version.").defaultValue("1.0.0"));
cliOptions.add(CliOption.newBoolean(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue(Boolean.TRUE.toString()));
cliOptions.add(CliOption.newBoolean(CodegenConstants.OPTIONAL_METHOD_ARGUMENT, "C# Optional method argument, " +
"e.g. void square(int x=10) (.net 4.0+ only)."));
// 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);
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
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
} else {
additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion);
}
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
apiPackage = packageName + ".Api";
modelPackage = packageName + ".Model";
clientPackage = packageName + ".Client";
} else {
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
}
additionalProperties.put("clientPackage", clientPackage);
@ -140,6 +144,35 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
additionalProperties.put("packageDescription", packageDescription);
additionalProperties.put("packageCompany", packageCompany);
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)) {
setOptionalMethodArgumentFlag(Boolean.valueOf(additionalProperties
@ -147,20 +180,73 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
}
additionalProperties.put("optionalMethodArgument", optionalMethodArgumentFlag);
supportingFiles.add(new SupportingFile("Configuration.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "Configuration.cs"));
supportingFiles.add(new SupportingFile("ApiClient.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiClient.cs"));
supportingFiles.add(new SupportingFile("ApiException.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "ApiException.cs"));
supportingFiles.add(new SupportingFile("ApiResponse.mustache",
sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator), "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("README.md", "", "README.md"));
supportingFiles.add(new SupportingFile("AssemblyInfo.mustache", "src" + File.separator + "Properties", "AssemblyInfo.cs"));
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_ASSEMBLY_INFO)) {
setOptionalAssemblyInfoFlag(Boolean.valueOf(additionalProperties
.get(CodegenConstants.OPTIONAL_ASSEMBLY_INFO).toString()));
}
String packageFolder = sourceFolder + File.separator + packageName.replace(".", java.io.File.separator);
String clientPackageDir = sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator);
//Compute the relative path to the bin directory where the external assemblies live
//This is necessary to properly generate the project file
int packageDepth = packageFolder.length() - packageFolder.replace(java.io.File.separator, "").length();
String binRelativePath = "..\\";
for (int i = 0; i < packageDepth; i = i + 1)
binRelativePath += "..\\";
binRelativePath += "vendor\\";
additionalProperties.put("binRelativePath", binRelativePath);
supportingFiles.add(new SupportingFile("Configuration.mustache",
clientPackageDir, "Configuration.cs"));
supportingFiles.add(new SupportingFile("ApiClient.mustache",
clientPackageDir, "ApiClient.cs"));
supportingFiles.add(new SupportingFile("ApiException.mustache",
clientPackageDir, "ApiException.cs"));
supportingFiles.add(new SupportingFile("ApiResponse.mustache",
clientPackageDir, "ApiResponse.cs"));
supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat"));
supportingFiles.add(new SupportingFile("compile-mono.sh.mustache", "", "compile-mono.sh"));
supportingFiles.add(new SupportingFile("packages.config.mustache", "vendor" + java.io.File.separator, "packages.config"));
supportingFiles.add(new SupportingFile("README.md", "", "README.md"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
if (optionalAssemblyInfoFlag) {
supportingFiles.add(new SupportingFile("AssemblyInfo.mustache", packageFolder + File.separator + "Properties", "AssemblyInfo.cs"));
}
if (optionalProjectFileFlag) {
supportingFiles.add(new SupportingFile("Project.mustache", packageFolder, clientPackage + ".csproj"));
}
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
super.postProcessOperations(objs);
if (objs != null) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation operation : ops) {
if (operation.returnType != null) {
operation.returnContainer = operation.returnType;
if (this.returnICollection && (
operation.returnType.startsWith("List") ||
operation.returnType.startsWith("Collection"))) {
// NOTE: ICollection works for both List<T> and Collection<T>
int genericStart = operation.returnType.indexOf("<");
if (genericStart > 0) {
operation.returnType = "ICollection" + operation.returnType.substring(genericStart);
}
}
}
}
}
}
return objs;
}
@Override
@ -178,132 +264,179 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
return "Generates a CSharp client library.";
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
public void setOptionalAssemblyInfoFlag(boolean flag) {
this.optionalAssemblyInfoFlag = flag;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar);
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 setOptionalProjectFileFlag(boolean flag) {
this.optionalProjectFileFlag = flag;
}
public void setPackageGuid(String packageGuid) {
this.packageGuid = packageGuid;
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar);
public Map<String, Object> postProcessModels(Map<String, Object> objMap) {
Map<String, Object> objs = super.postProcessModels(objMap);
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;
}
@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;
if (allowableValues == null) {
continue;
}
List<String> values = (List<String>) allowableValues.get("values");
if (values == null) {
continue;
}
// 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;
}
// 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 {
type = swaggerType;
enumName = value.substring(truncateIdx);
if ("".equals(enumName)) {
enumName = value;
}
return toModelName(type);
}
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
// HACK: strip ? from enum
if (var.datatypeWithEnum != null) {
var.vendorExtensions.put(DATA_TYPE_WITH_ENUM_EXTENSION, var.datatypeWithEnum.substring(0, var.datatypeWithEnum.length() - 1));
}
@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");
if (var.defaultValue != null) {
String enumName = null;
for (Map<String, String> enumVar : enumVars) {
if (var.defaultValue.replace("\"", "").equals(enumVar.get("value"))) {
enumName = enumVar.get("name");
break;
}
}
if (enumName != null && var.vendorExtensions.containsKey(DATA_TYPE_WITH_ENUM_EXTENSION)) {
var.defaultValue = var.vendorExtensions.get(DATA_TYPE_WITH_ENUM_EXTENSION) + "." + enumName;
}
}
// 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));
return objs;
}
public void setOptionalMethodArgumentFlag(boolean flag) {
this.optionalMethodArgumentFlag = flag;
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;
}
}
public void setPackageName(String packageName) {
this.packageName = packageName;
@ -313,68 +446,11 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
this.packageVersion = packageVersion;
}
@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;
public void setTargetFrameworkNuget(String targetFrameworkNuget) {
this.targetFrameworkNuget = targetFrameworkNuget;
}
/**
* 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;
public void setSupportsAsync(Boolean supportsAsync){
this.supportsAsync = supportsAsync;
}
}

View File

@ -143,6 +143,13 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
final String baseNamespaceFolder = sourceFolder + File.separator + namespaceToFolder(baseNamespace);
supportingFiles.add(new SupportingFile("project.mustache", "", "project.clj"));
supportingFiles.add(new SupportingFile("core.mustache", baseNamespaceFolder, "core.clj"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
}
@Override
public String sanitizeTag(String tag) {
return tag.replaceAll("[^a-zA-Z_]+", "_");
}
@Override
@ -160,6 +167,11 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
return dashize(sanitizeName(operationId));
}
@Override
public String toApiFilename(String name) {
return underscore(toApiName(name));
}
@Override
public String toApiName(String name) {
return dashize(name);
@ -172,7 +184,7 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
@Override
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);
return name;
}
@ -196,6 +208,7 @@ public class ClojureClientCodegen extends DefaultCodegen implements CodegenConfi
return operations;
}
@SuppressWarnings("static-method")
protected String namespaceToFolder(String ns) {
return ns.replace(".", File.separator).replace("-", "_");
}

View File

@ -31,7 +31,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
apiPackage = "IO.Swagger.Api";
modelPackage = "IO.Swagger.Model";
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
// local variable names in API methods (endpoints)
"path", "queryParams", "headerParams", "formParams", "fileParams", "postBody",
@ -172,7 +172,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
@Override
public String toVarName(String name) {
// 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 (name.matches("^[A-Z_]*$")) {
@ -184,7 +184,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
name = camelize(name);
// 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);
}
@ -206,7 +206,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
name = camelize(name, true);
// 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);
}
@ -215,8 +215,10 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
@Override
public String toModelName(String name) {
name = sanitizeName(name);
// 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");
}
@ -265,7 +267,7 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
@Override
public String toOperationId(String operationId) {
// 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");
}

View File

@ -35,7 +35,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
apiPackage = "lib.api";
modelPackage = "lib.model";
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
"abstract", "as", "assert", "async", "async*", "await",
"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("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(PUB_NAME, "Name in generated pubspec"));
@ -147,6 +150,9 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("auth/http_basic_auth.mustache", authFolder, "http_basic_auth.dart"));
supportingFiles.add(new SupportingFile("auth/api_key_auth.mustache", authFolder, "api_key_auth.dart"));
supportingFiles.add(new SupportingFile("auth/oauth.mustache", authFolder, "oauth.dart"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
}
@ -168,7 +174,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toVarName(String name) {
// 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 (name.matches("^[A-Z_]*$")) {
@ -180,7 +186,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
name = camelize(name, true);
// 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);
}
@ -196,7 +202,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toModelName(String name) {
// 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");
}
@ -218,15 +224,10 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toDefaultValue(Property p) {
if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "{}";
} else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "[]";
}
return super.toDefaultValue(p);
}
@ -263,7 +264,7 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toOperationId(String operationId) {
// 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");
}

View File

@ -29,7 +29,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
protected String packageVersion;
protected String invokerPackage = "io.swagger";
protected String sourceFolder = "src/main/flex";
protected String sourceFolder = "flash";
public FlashClientCodegen() {
super();
@ -63,12 +63,15 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("DateTime", "Date");
typeMapping.put("object", "Object");
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.put("File", "flash.filesystem.File");
// 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",
"var", "delete", "if", "on", "void", "do", "ifFrameLoaded", "onClipEvent", "while",
"else", "in", "or", "with", "eq", "le", "return"));
@ -80,7 +83,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
.defaultValue("1.0.0"));
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, CodegenConstants.INVOKER_PACKAGE_DESC));
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";
//apiPackage = invokerPackage + File.separatorChar + "client" + File.separatorChar + "api";
final String invokerFolder = (sourceFolder + File.separator + invokerPackage + File.separator
+ "swagger" + File.separator).replace(".", File.separator).replace('.', File.separatorChar);
final String invokerFolder = (sourceFolder + File.separator + "src/" + invokerPackage + File.separator).replace(".", File.separator).replace('.', File.separatorChar);
supportingFiles.add(new SupportingFile("ApiInvoker.as", invokerFolder + "common", "ApiInvoker.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("SwaggerApi.as", invokerFolder + "common", "SwaggerApi.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("ApiClientEvent.as", invokerFolder + "event", "ApiClientEvent.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.xml", sourceFolder, "build.xml"));
supportingFiles.add(new SupportingFile("AirExecutorApp-app.xml", sourceFolder + File.separatorChar
+ "bin", "AirExecutorApp-app.xml"));
supportingFiles.add(new SupportingFile("README.txt", sourceFolder, "README.txt"));
//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
+ "lib", "ASAXB-0.1.1.swc"));
supportingFiles.add(new SupportingFile("as3corelib.swc", sourceFolder + File.separatorChar
@ -150,6 +153,8 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
+ File.separator + "lib" + File.separator + "ext", "flexunit-cilistener-4.1.0_RC2-28-3.5.0.12683.swc"));
supportingFiles.add(new SupportingFile("flexunit-core-flex-4.0.0.2-sdk3.5.0.12683.swc", sourceFolder
+ File.separator + "lib" + File.separator + "ext", "flexunit-core-flex-4.0.0.2-sdk3.5.0.12683.swc"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
}
private static String dropDots(String str) {
@ -178,26 +183,19 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
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);
}
@Override
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);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p);
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
if (p instanceof ArrayProperty || p instanceof MapProperty) {
return getSwaggerType(p);
}
return super.getTypeDeclaration(p);
@ -253,22 +251,18 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
}
return "0";
} else if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return "new Dictionary()";
} else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return "new Array()";
} else {
return "null";
return "NaN";
}
}
@Override
public String toVarName(String name) {
// 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 (name.matches("^[A-Z_]*$")) {
@ -280,7 +274,7 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
name = camelize(dropDots(name), true);
// 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);
}
@ -295,9 +289,20 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
@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 (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
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
@ -307,20 +312,14 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
public String toModelFilename(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");
}
// underscore the model file name
// PhoneNumber => phone_number
return camelize(dropDots(name));
// leverage toModelName
return dropDots(toModelName(name));
}
@Override
public String toApiFilename(String name) {
// 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
return camelize(name) + "Api";
@ -351,8 +350,9 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
}
// 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");
if (isReservedWord(operationId)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore(sanitizeName("call_" + operationId)));
operationId = "call_" + operationId;
}
return underscore(operationId);
@ -373,7 +373,4 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
public void setSourceFolder(String 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.Lists;
import com.google.common.collect.Multimap;
import config.ConfigParser;
import io.swagger.codegen.*;
import io.swagger.models.HttpMethod;
import io.swagger.models.Operation;
@ -14,7 +16,13 @@ import io.swagger.util.Yaml;
import java.io.File;
import java.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 DEFAULT_CONTROLLER = "defaultController";
@ -65,7 +73,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
embeddedTemplateDir = templateDir = "flaskConnexion";
// from https://docs.python.org/release/2.5.4/ref/keywords.html
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
"assert", "else", "if", "pass", "yield", "break", "except", "import",
@ -167,8 +175,8 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
*/
@Override
public String getHelp() {
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.";
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.";
}
@Override
@ -249,7 +257,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
}
@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>>();
Map<String, Object> apiInfo = (Map<String, Object>) objs.get("apiInfo");
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;
}
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();
for (CodegenOperation op : ops) {
@ -289,7 +297,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) {
e.printStackTrace();
LOGGER.error(e.getMessage(), e);
}
}
for (Map<String, Object> operations : getOperations(objs)) {
@ -304,7 +312,7 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
@Override
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.
// controllers.defaultController.addPet => addPet
operationId = operationId.replaceAll(".*\\.", "");

View File

@ -0,0 +1,336 @@
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"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
}
@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.Swagger;
import io.swagger.models.properties.*;
import org.apache.commons.lang.StringUtils;
import java.util.*;
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.Parameter;
import io.swagger.models.properties.*;
import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.util.*;
import java.util.regex.Pattern;
public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
@SuppressWarnings("hiding")
private static final Logger LOGGER = LoggerFactory.getLogger(JavaClientCodegen.class);
public static final String FULL_JAVA_UTIL = "fullJavaUtil";
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 groupId = "io.swagger";
protected String artifactId = "swagger-java-client";
@ -32,6 +41,9 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String javaUtilPrefix = "";
protected Boolean serializableModel = false;
protected boolean serializeBigDecimalAsString = false;
protected boolean useRxJava = false;
protected boolean hideGenerationTimestamp = false;
public JavaClientCodegen() {
super();
@ -42,11 +54,12 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
// used as internal variables, can collide with parameter names
"path", "queryParams", "headerParams", "formParams", "postBody", "accepts", "accept", "contentTypes",
"contentType", "authNames",
"localVarPath", "localVarQueryParams", "localVarHeaderParams", "localVarFormParams",
"localVarPostBody", "localVarAccepts", "localVarAccept", "localVarContentTypes",
"localVarContentType", "localVarAuthNames", "localReturnType",
// language reserved words
"abstract", "continue", "for", "new", "switch", "assert",
@ -72,6 +85,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
);
instantiationTypes.put("array", "ArrayList");
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.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
@ -85,18 +100,29 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(CliOption.newBoolean(CodegenConstants.SERIALIZE_BIG_DECIMAL_AS_STRING, CodegenConstants
.SERIALIZE_BIG_DECIMAL_AS_STRING_DESC));
cliOptions.add(CliOption.newBoolean(FULL_JAVA_UTIL, "whether to use fully qualified name for classes under java.util"));
cliOptions.add(CliOption.newBoolean(USE_RX_JAVA, "Whether to use the RxJava adapter with the retrofit2 library."));
cliOptions.add(new CliOption("hideGenerationTimestamp", "hides the timestamp when files were generated"));
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("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("retrofit", "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_1, "HTTP client: OkHttp 2.4.0. JSON processing: Gson 2.3.1 (Retrofit 1.9.0)");
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");
library.setDefault(DEFAULT_LIBRARY);
library.setEnum(supportedLibraries);
library.setDefault(DEFAULT_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
@ -172,12 +198,18 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
if (additionalProperties.containsKey(FULL_JAVA_UTIL)) {
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) {
javaUtilPrefix = "java.util.";
}
additionalProperties.put(FULL_JAVA_UTIL, fullJavaUtil);
additionalProperties.put("javaUtilPrefix", javaUtilPrefix);
importMapping.put("List", "java.util.List");
if (fullJavaUtil) {
typeMapping.put("array", "java.util.List");
typeMapping.put("map", "java.util.Map");
@ -211,26 +243,25 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
importMapping.put("StringUtil", invokerPackage + ".StringUtil");
final String invokerFolder = (sourceFolder + '/' + invokerPackage).replace(".", "/");
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("build.gradle.mustache", "", "build.gradle"));
supportingFiles.add(new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
supportingFiles.add(new SupportingFile("gradle.properties.mustache", "", "gradle.properties"));
supportingFiles.add(new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java"));
writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml"));
writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md"));
writeOptional(outputFolder, new SupportingFile("build.gradle.mustache", "", "build.gradle"));
writeOptional(outputFolder, new SupportingFile("settings.gradle.mustache", "", "settings.gradle"));
writeOptional(outputFolder, new SupportingFile("gradle.properties.mustache", "", "gradle.properties"));
writeOptional(outputFolder, new SupportingFile("manifest.mustache", projectFolder, "AndroidManifest.xml"));
writeOptional(outputFolder, new SupportingFile("ApiClient.mustache", invokerFolder, "ApiClient.java"));
supportingFiles.add(new SupportingFile("StringUtil.mustache", invokerFolder, "StringUtil.java"));
final String authFolder = (sourceFolder + '/' + invokerPackage + ".auth").replace(".", "/");
if ("feign".equals(getLibrary())) {
supportingFiles.add(new SupportingFile("FormAwareEncoder.mustache", invokerFolder, "FormAwareEncoder.java"));
} else {
}
supportingFiles.add(new SupportingFile("auth/HttpBasicAuth.mustache", authFolder, "HttpBasicAuth.java"));
supportingFiles.add(new SupportingFile("auth/ApiKeyAuth.mustache", authFolder, "ApiKeyAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuth.mustache", authFolder, "OAuth.java"));
supportingFiles.add(new SupportingFile("auth/OAuthFlow.mustache", authFolder, "OAuthFlow.java"));
}
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("Configuration.mustache", invokerFolder, "Configuration.java"));
supportingFiles.add(new SupportingFile("Pair.mustache", invokerFolder, "Pair.java"));
@ -247,12 +278,44 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("ProgressResponseBody.mustache", invokerFolder, "ProgressResponseBody.java"));
// "build.sbt" is for development with 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("CollectionFormats.mustache", invokerFolder, "CollectionFormats.java"));
} else if("jersey2".equals(getLibrary())) {
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");
}
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
}
private boolean usesAnyRetrofitLibrary() {
return getLibrary() != null && getLibrary().contains(RETROFIT_1);
}
private boolean usesRetrofit2Library() {
return getLibrary() != null && getLibrary().contains(RETROFIT_2);
}
private void sanitizeConfig() {
@ -293,7 +356,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toVarName(String 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)) {
name = "_u";
@ -309,7 +372,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
name = camelize(name, true);
// 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);
}
@ -323,17 +386,28 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
}
@Override
public String toModelName(String name) {
name = sanitizeName(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");
}
public String toModelName(final String name) {
final String sanitizedName = sanitizeName(modelNamePrefix + name + modelNameSuffix);
// camelize the model name
// 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;
}
// model name starts with number
if (name.matches("^\\d.*")) {
final String modelName = "Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize)
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return camelizedName;
}
@Override
@ -429,7 +503,9 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
String type = null;
if (typeMapping.containsKey(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;
}
} else {
@ -448,22 +524,28 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
throw new RuntimeException("Empty method/operation name (operationId) not allowed");
}
operationId = camelize(sanitizeName(operationId), true);
// 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");
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;
}
return camelize(sanitizeName(operationId), true);
return operationId;
}
@Override
public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
if(codegenModel.description != null) {
codegenModel.imports.add("ApiModel");
}
if (allDefinitions != null && codegenModel != null && codegenModel.parentSchema != null && codegenModel.hasEnums) {
final Model parentModel = allDefinitions.get(codegenModel.parentSchema);
final CodegenModel parentCodegenModel = super.fromModel(codegenModel.parent, parentModel);
codegenModel = this.reconcileInlineEnums(codegenModel, parentCodegenModel);
codegenModel = JavaClientCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel);
}
return codegenModel;
@ -482,7 +564,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
model.imports.add("ApiModelProperty");
model.imports.add("ApiModel");
@ -493,7 +581,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
if(StringUtils.isEmpty(lib) || "feign".equals(lib) || "jersey2".equals(lib)) {
model.imports.add("JsonProperty");
if(model.hasEnums != null || model.hasEnums == true) {
if(BooleanUtils.toBoolean(model.hasEnums)) {
model.imports.add("JsonValue");
}
}
@ -512,6 +600,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
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;
@ -568,7 +657,18 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
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");
if (operations != null) {
List<CodegenOperation> ops = (List<CodegenOperation>) operations.get("operation");
@ -584,7 +684,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
if (operation.returnType == null) {
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);
}
}
@ -618,7 +718,7 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
}
}
private String getAccept(Operation operation) {
private static String getAccept(Operation operation) {
String accepts = null;
String defaultContentType = "application/json";
if (operation.getProduces() != null && !operation.getProduces().isEmpty()) {
@ -649,14 +749,14 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
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()]));
// 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) {
private static String toEnumVarName(String value) {
String var = value.replaceAll("\\W+", "_").toUpperCase();
if (var.matches("\\d.*")) {
return "_" + var;
@ -665,7 +765,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
// 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
@ -749,8 +849,8 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
this.serializableModel = serializableModel;
}
private String sanitizePackageName(String packageName) {
packageName = packageName.trim();
private static String sanitizePackageName(String packageName) {
packageName = packageName.trim(); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
packageName = packageName.replaceAll("[^a-zA-Z0-9_\\.]", "_");
if(Strings.isNullOrEmpty(packageName)) {
return "invalidPackageName";
@ -761,4 +861,12 @@ public class JavaClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setFullJavaUtil(boolean 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.Property;
import io.swagger.util.Yaml;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
public class JavaInflectorServerCodegen extends JavaClientCodegen implements CodegenConfig {
protected String title = "Swagger Inflector";
public class JavaInflectorServerCodegen extends JavaClientCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(JavaInflectorServerCodegen.class);
protected String title = "Swagger Inflector";
protected String implFolder = "src/main/java";
public JavaInflectorServerCodegen() {
super();
sourceFolder = "src/main/java";
sourceFolder = "src/gen/java";
modelTemplateFiles.put("model.mustache", ".java");
apiTemplateFiles.put("api.mustache", ".java");
embeddedTemplateDir = templateDir = "JavaInflector";
@ -35,6 +40,7 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"byte[]",
"String",
"boolean",
"Boolean",
@ -65,10 +71,10 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
super.processOpts();
supportingFiles.clear();
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("web.mustache", "src/main/webapp/WEB-INF", "web.xml"));
supportingFiles.add(new SupportingFile("inflector.mustache", "", "inflector.yaml"));
writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml"));
writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md"));
writeOptional(outputFolder, new SupportingFile("web.mustache", "src/main/webapp/WEB-INF", "web.xml"));
writeOptional(outputFolder, new SupportingFile("inflector.mustache", "", "inflector.yaml"));
supportingFiles.add(new SupportingFile("swagger.mustache",
"src/main/swagger",
"swagger.yaml")
@ -77,21 +83,6 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
(sourceFolder + '/' + invokerPackage).replace(".", "/"), "StringUtil.java"));
}
@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 getTypeDeclaration(inner);
}
return super.getTypeDeclaration(p);
}
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
String basePath = resourcePath;
@ -155,6 +146,18 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
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
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
@ -163,7 +166,7 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) {
e.printStackTrace();
LOGGER.error(e.getMessage(), e);
}
}
return super.postProcessSupportingFileData(objs);
@ -174,12 +177,7 @@ public class JavaInflectorServerCodegen extends JavaClientCodegen implements Cod
if (name.length() == 0) {
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";
}
@Override
public boolean shouldOverwrite(String filename) {
return super.shouldOverwrite(filename);
}
}

View File

@ -0,0 +1,155 @@
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");
supportedLibraries.put("jersey2", "Jersey core 2.x");
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"));
supportingFiles.add(new SupportingFile("jacksonJsonProvider.mustache", (sourceFolder + '/' + apiPackage).replace(".", "/"), "JacksonJsonProvider.java"));
writeOptional(outputFolder, new SupportingFile("bootstrap.mustache", (implFolder + '/' + apiPackage).replace(".", "/"), "Bootstrap.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(DEFAULT_LIBRARY.equals(library) || library == null) {
if(templateDir.startsWith(JAXRS_TEMPLATE_DIRECTORY_NAME)) {
// set to the default location
templateDir = JAXRS_TEMPLATE_DIRECTORY_NAME + File.separator + "jersey1_18";
}
else {
templateDir += File.separator + "jersey1_18";
}
}
if("jersey2".equals(library)) {
if(templateDir.startsWith(JAXRS_TEMPLATE_DIRECTORY_NAME)) {
// set to the default location
templateDir = JAXRS_TEMPLATE_DIRECTORY_NAME + File.separator + "jersey2";
}
else {
templateDir += File.separator + "jersey2";
}
}
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;
}
public void hideGenerationTimestamp(boolean hideGenerationTimestamp) {
this.hideGenerationTimestamp = hideGenerationTimestamp;
}
}

View File

@ -4,22 +4,26 @@ import io.swagger.codegen.*;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
import org.apache.commons.lang.StringUtils;
import java.io.File;
import java.util.*;
public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConfig {
public class JavaResteasyServerCodegen extends JavaClientCodegen implements CodegenConfig {
protected String dateLibrary = "default";
protected String title = "Swagger Server";
protected String implFolder = "src/main/java";
public static final String DATE_LIBRARY = "dateLibrary";
public JaxRSServerCodegen() {
public JavaResteasyServerCodegen() {
super();
sourceFolder = "src/gen/java";
invokerPackage = "io.swagger.api";
artifactId = "swagger-jaxrs-server";
artifactId = "swagger-jaxrs-resteasy-server";
outputFolder = "generated-code/javaJaxRS";
modelTemplateFiles.put("model.mustache", ".java");
@ -32,10 +36,10 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
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++) {
if(CodegenConstants.LIBRARY.equals(cliOptions.get(i).getOpt())) {
for (int i = 0; i < cliOptions.size(); i++) {
if (CodegenConstants.LIBRARY.equals(cliOptions.get(i).getOpt())) {
cliOptions.remove(i);
break;
}
@ -54,8 +58,7 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
Map<String, String> supportedLibraries = new LinkedHashMap<String, String>();
supportedLibraries.put(DEFAULT_LIBRARY, "Jersey core 1.18.1");
// supportedLibraries.put("jersey2", "Jersey2 core library 2.x");
supportedLibraries.put(DEFAULT_LIBRARY, "Resteasy core 3.0.11");
library.setEnum(supportedLibraries);
cliOptions.add(library);
@ -69,29 +72,27 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
@Override
public String getName() {
return "jaxrs";
return "jaxrs-resteasy";
}
@Override
public String getHelp() {
return "Generates a Java JAXRS Server application.";
return "Generates a Java JAXRS-Resteasy Server application.";
}
@Override
public void processOpts() {
super.processOpts();
if(additionalProperties.containsKey(CodegenConstants.IMPL_FOLDER)) {
if (additionalProperties.containsKey(CodegenConstants.IMPL_FOLDER)) {
implFolder = (String) additionalProperties.get(CodegenConstants.IMPL_FOLDER);
}
// if("jersey2".equals(getLibrary())) {
// embeddedTemplateDir = templateDir = "JavaJaxRS" + File.separator + "jersey2";
// }
supportingFiles.clear();
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml"));
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",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiException.java"));
supportingFiles.add(new SupportingFile("ApiOriginFilter.mustache",
@ -100,29 +101,35 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
(sourceFolder + '/' + apiPackage).replace(".", "/"), "ApiResponseMessage.java"));
supportingFiles.add(new SupportingFile("NotFoundException.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "NotFoundException.java"));
supportingFiles.add(new SupportingFile("web.mustache",
writeOptional(outputFolder, new SupportingFile("web.mustache",
("src/main/webapp/WEB-INF"), "web.xml"));
writeOptional(outputFolder, new SupportingFile("jboss-web.mustache",
("src/main/webapp/WEB-INF"), "jboss-web.xml"));
writeOptional(outputFolder, new SupportingFile("RestApplication.mustache",
(sourceFolder + '/' + invokerPackage).replace(".", "/"), "RestApplication.java"));
supportingFiles.add(new SupportingFile("StringUtil.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "StringUtil.java"));
(sourceFolder + '/' + invokerPackage).replace(".", "/"), "StringUtil.java"));
if (additionalProperties.containsKey("dateLibrary")) {
setDateLibrary(additionalProperties.get("dateLibrary").toString());
additionalProperties.put(dateLibrary, "true");
}
if("joda".equals(dateLibrary)) {
if ("joda".equals(dateLibrary)) {
typeMapping.put("date", "LocalDate");
typeMapping.put("DateTime", "DateTime");
importMapping.put("LocalDate", "org.joda.time.LocalDate");
importMapping.put("DateTime", "org.joda.time.DateTime");
supportingFiles.add(new SupportingFile("JacksonConfig.mustache",
(sourceFolder + '/' + invokerPackage).replace(".", "/"), "JacksonConfig.java"));
supportingFiles.add(new SupportingFile("JodaDateTimeProvider.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "JodaDateTimeProvider.java"));
supportingFiles.add(new SupportingFile("JodaLocalDateProvider.mustache",
(sourceFolder + '/' + apiPackage).replace(".", "/"), "JodaLocalDateProvider.java"));
}
else if ("java8".equals(dateLibrary)) {
} else if ("java8".equals(dateLibrary)) {
additionalProperties.put("java8", "true");
additionalProperties.put("javaVersion", "1.8");
typeMapping.put("date", "LocalDate");
@ -165,38 +172,39 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
co.baseName = basePath;
}
@Override
public void preprocessSwagger(Swagger swagger) {
if("/".equals(swagger.getBasePath())) {
if ("/".equals(swagger.getBasePath())) {
swagger.setBasePath("");
}
String host = swagger.getHost();
String port = "8080";
if(host != null) {
if (host != null) {
String[] parts = host.split(":");
if(parts.length > 1) {
if (parts.length > 1) {
port = parts[1];
}
}
this.additionalProperties.put("serverPort", port);
if(swagger != null && swagger.getPaths() != null) {
for(String pathname : swagger.getPaths().keySet()) {
if (swagger != null && 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) {
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()) {
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) {
if (tags.size() > 0) {
tags.get(tags.size() - 1).remove("hasMore");
}
if(operation.getTags().size() > 0) {
if (operation.getTags().size() > 0) {
String tag = operation.getTags().get(0);
operation.setTags(Arrays.asList(tag));
}
@ -208,12 +216,22 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
}
}
@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.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;
if (responses != null) {
for (CodegenResponse resp : responses) {
@ -260,6 +278,7 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
return camelize(name) + "Api";
}
@Override
public String apiFilename(String templateName, String tag) {
@ -283,6 +302,7 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
return result;
}
private String implFileFolder(String output) {
return outputFolder + "/" + output + "/" + apiPackage().replace('.', '/');
}
@ -295,4 +315,31 @@ public class JaxRSServerCodegen extends JavaClientCodegen implements CodegenConf
public void setDateLibrary(String library) {
this.dateLibrary = library;
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
if(serializeBigDecimalAsString) {
if (property.baseType.equals("BigDecimal")) {
// we serialize BigDecimal as `string` to avoid precision loss
property.vendorExtensions.put("extraAnnotation", "@JsonSerialize(using = ToStringSerializer.class)");
// this requires some more imports to be added for this model...
model.imports.add("ToStringSerializer");
model.imports.add("JsonSerialize");
}
}
if(model.isEnum == null || model.isEnum) {
final String lib = getLibrary();
if(StringUtils.isEmpty(lib)) {
model.imports.add("JsonProperty");
if(model.hasEnums != null || model.hasEnums == true) {
model.imports.add("JsonValue");
}
}
}
return;
}
}

View File

@ -7,16 +7,32 @@ import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenParameter;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
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.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.MapProperty;
import io.swagger.models.properties.Property;
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.util.ArrayList;
@ -27,26 +43,33 @@ import java.util.Iterator;
import java.util.List;
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 {
@SuppressWarnings("hiding")
private static final Logger LOGGER = LoggerFactory.getLogger(JavascriptClientCodegen.class);
private static final String PROJECT_NAME = "projectName";
private static final String MODULE_NAME = "moduleName";
private static final String PROJECT_DESCRIPTION = "projectDescription";
private static final String PROJECT_VERSION = "projectVersion";
private static final String PROJECT_LICENSE_NAME = "projectLicenseName";
public static final String PROJECT_NAME = "projectName";
public static final String MODULE_NAME = "moduleName";
public static final String PROJECT_DESCRIPTION = "projectDescription";
public static final String PROJECT_VERSION = "projectVersion";
public static final String PROJECT_LICENSE_NAME = "projectLicenseName";
public static final String USE_PROMISES = "usePromises";
public static final String USE_INHERITANCE = "useInheritance";
public static final String EMIT_MODEL_METHODS = "emitModelMethods";
public static final String EMIT_JS_DOC = "emitJSDoc";
protected String projectName;
protected String moduleName;
protected String projectDescription;
protected String projectVersion;
protected String projectLicenseName;
protected String sourceFolder = "src";
protected String localVariablePrefix = "";
protected boolean usePromises;
protected boolean emitModelMethods;
protected boolean emitJSDoc = true;
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
public JavascriptClientCodegen() {
super();
@ -56,9 +79,11 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
templateDir = "Javascript";
apiPackage = "api";
modelPackage = "model";
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
// reference: http://www.w3schools.com/js/js_reserved.asp
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
"abstract", "arguments", "boolean", "break", "byte",
"case", "catch", "char", "class", "const",
@ -84,8 +109,36 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
);
defaultIncludes = new HashSet<String>(languageSpecificPrimitives);
instantiationTypes.put("array", "Array");
instantiationTypes.put("list", "Array");
instantiationTypes.put("map", "Object");
typeMapping.clear();
typeMapping.put("array", "Array");
typeMapping.put("map", "Object");
typeMapping.put("List", "Array");
typeMapping.put("boolean", "Boolean");
typeMapping.put("string", "String");
typeMapping.put("int", "Integer"); // Huh? What is JS Integer?
typeMapping.put("float", "Number");
typeMapping.put("number", "Number");
typeMapping.put("DateTime", "Date"); // Should this be dateTime?
typeMapping.put("Date", "Date"); // Should this be date?
typeMapping.put("long", "Integer");
typeMapping.put("short", "Integer");
typeMapping.put("char", "String");
typeMapping.put("double", "Number");
typeMapping.put("object", "Object");
typeMapping.put("integer", "Integer");
// binary not supported in JavaScript client right now, using String as a workaround
typeMapping.put("ByteArray", "String"); // I don't see ByteArray defined in the Swagger docs.
typeMapping.put("binary", "String");
importMapping.clear();
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC).defaultValue("src"));
cliOptions.add(new CliOption(CodegenConstants.LOCAL_VARIABLE_PREFIX, CodegenConstants.LOCAL_VARIABLE_PREFIX_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(PROJECT_NAME,
"name of the project (Default: generated from info.title or \"swagger-js-client\")"));
cliOptions.add(new CliOption(MODULE_NAME,
@ -96,6 +149,18 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
"version of the project (Default: using info.version or \"1.0.0\")"));
cliOptions.add(new CliOption(PROJECT_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(EMIT_MODEL_METHODS,
"generate getters and setters for model properties")
.defaultValue(Boolean.FALSE.toString()));
cliOptions.add(new CliOption(EMIT_JS_DOC,
"generate JSDoc comments")
.defaultValue(Boolean.TRUE.toString()));
cliOptions.add(new CliOption(USE_INHERITANCE,
"use JavaScript prototype chains & delegation for inheritance")
.defaultValue(Boolean.TRUE.toString()));
}
@Override
@ -117,56 +182,54 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
public void processOpts() {
super.processOpts();
typeMapping = new HashMap<String, String>();
typeMapping.put("array", "Array");
typeMapping.put("List", "Array");
typeMapping.put("map", "Object");
typeMapping.put("object", "Object");
typeMapping.put("boolean", "Boolean");
typeMapping.put("char", "String");
typeMapping.put("string", "String");
typeMapping.put("short", "Integer");
typeMapping.put("int", "Integer");
typeMapping.put("integer", "Integer");
typeMapping.put("long", "Integer");
typeMapping.put("float", "Number");
typeMapping.put("double", "Number");
typeMapping.put("number", "Number");
typeMapping.put("DateTime", "Date");
importMapping.clear();
if (additionalProperties.containsKey(PROJECT_NAME)) {
setProjectName(((String) additionalProperties.get(PROJECT_NAME)));
}
if (additionalProperties.containsKey(MODULE_NAME)) {
setModuleName(((String) additionalProperties.get(MODULE_NAME)));
}
if (additionalProperties.containsKey(PROJECT_DESCRIPTION)) {
setProjectDescription(((String) additionalProperties.get(PROJECT_DESCRIPTION)));
}
if (additionalProperties.containsKey(PROJECT_VERSION)) {
setProjectVersion(((String) additionalProperties.get(PROJECT_VERSION)));
}
if (additionalProperties.containsKey(PROJECT_LICENSE_NAME)) {
setProjectLicenseName(((String) additionalProperties.get(PROJECT_LICENSE_NAME)));
}
if (additionalProperties.containsKey(CodegenConstants.LOCAL_VARIABLE_PREFIX)) {
setLocalVariablePrefix((String) additionalProperties.get(CodegenConstants.LOCAL_VARIABLE_PREFIX));
}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER));
}
if (additionalProperties.containsKey(USE_PROMISES)) {
setUsePromises(Boolean.parseBoolean((String)additionalProperties.get(USE_PROMISES)));
}
if (additionalProperties.containsKey(USE_INHERITANCE)) {
setUseInheritance(Boolean.parseBoolean((String)additionalProperties.get(USE_INHERITANCE)));
} else {
supportsInheritance = true;
}
if (additionalProperties.containsKey(EMIT_MODEL_METHODS)) {
setEmitModelMethods(Boolean.parseBoolean((String)additionalProperties.get(EMIT_MODEL_METHODS)));
}
if (additionalProperties.containsKey(EMIT_JS_DOC)) {
setEmitJSDoc(Boolean.parseBoolean((String)additionalProperties.get(EMIT_JS_DOC)));
}
}
@Override
public void preprocessSwagger(Swagger swagger) {
super.preprocessSwagger(swagger);
if (additionalProperties.containsKey(PROJECT_NAME)) {
projectName = ((String) additionalProperties.get(PROJECT_NAME));
}
if (additionalProperties.containsKey(MODULE_NAME)) {
moduleName = ((String) additionalProperties.get(MODULE_NAME));
}
if (additionalProperties.containsKey(PROJECT_DESCRIPTION)) {
projectDescription = ((String) additionalProperties.get(PROJECT_DESCRIPTION));
}
if (additionalProperties.containsKey(PROJECT_VERSION)) {
projectVersion = ((String) additionalProperties.get(PROJECT_VERSION));
}
if (additionalProperties.containsKey(CodegenConstants.LOCAL_VARIABLE_PREFIX)) {
localVariablePrefix = (String) additionalProperties.get(CodegenConstants.LOCAL_VARIABLE_PREFIX);
}
if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) {
sourceFolder = (String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER);
}
if (swagger.getInfo() != null) {
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
projectName = dashize(info.getTitle());
}
if (projectVersion == null) {
if (StringUtils.isBlank(projectVersion)) {
// when projectVersion is not specified, use info.version
projectVersion = info.getVersion();
}
@ -174,22 +237,23 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
// when projectDescription is not specified, use info.description
projectDescription = info.getDescription();
}
if (additionalProperties.get(PROJECT_LICENSE_NAME) == null) {
// when projectLicense is not specified, use info.license
if (info.getLicense() != null) {
License license = info.getLicense();
if (additionalProperties.get(PROJECT_LICENSE_NAME) == null) {
additionalProperties.put(PROJECT_LICENSE_NAME, license.getName());
}
}
}
// default values
if (projectName == null) {
if (StringUtils.isBlank(projectName)) {
projectName = "swagger-js-client";
}
if (moduleName == null) {
if (StringUtils.isBlank(moduleName)) {
moduleName = camelize(underscore(projectName));
}
if (projectVersion == null) {
if (StringUtils.isBlank(projectVersion)) {
projectVersion = "1.0.0";
}
if (projectDescription == null) {
@ -200,11 +264,24 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
additionalProperties.put(MODULE_NAME, moduleName);
additionalProperties.put(PROJECT_DESCRIPTION, escapeText(projectDescription));
additionalProperties.put(PROJECT_VERSION, projectVersion);
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
additionalProperties.put(CodegenConstants.LOCAL_VARIABLE_PREFIX, localVariablePrefix);
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
additionalProperties.put(CodegenConstants.SOURCE_FOLDER, sourceFolder);
additionalProperties.put(USE_PROMISES, usePromises);
additionalProperties.put(USE_INHERITANCE, supportsInheritance);
additionalProperties.put(EMIT_MODEL_METHODS, emitModelMethods);
additionalProperties.put(EMIT_JS_DOC, emitJSDoc);
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
supportingFiles.add(new SupportingFile("package.mustache", "", "package.json"));
supportingFiles.add(new SupportingFile("index.mustache", sourceFolder, "index.js"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", sourceFolder, "ApiClient.js"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
}
@Override
@ -214,18 +291,82 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', File.separatorChar);
return outputFolder + '/' + sourceFolder + '/' + apiPackage().replace('.', '/');
}
@Override
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', File.separatorChar);
return outputFolder + '/' + sourceFolder + '/' + modelPackage().replace('.', '/');
}
public void setSourceFolder(String sourceFolder) {
this.sourceFolder = sourceFolder;
}
public void setProjectName(String projectName) {
this.projectName = projectName;
}
public void setLocalVariablePrefix(String localVariablePrefix) {
this.localVariablePrefix = localVariablePrefix;
}
public void setModuleName(String moduleName) {
this.moduleName = moduleName;
}
public void setProjectDescription(String projectDescription) {
this.projectDescription = projectDescription;
}
public void setProjectVersion(String projectVersion) {
this.projectVersion = projectVersion;
}
public void setProjectLicenseName(String projectLicenseName) {
this.projectLicenseName = projectLicenseName;
}
public void setUsePromises(boolean usePromises) {
this.usePromises = usePromises;
}
public void setUseInheritance(boolean useInheritance) {
this.supportsInheritance = useInheritance;
}
public void setEmitModelMethods(boolean emitModelMethods) {
this.emitModelMethods = emitModelMethods;
}
public void setEmitJSDoc(boolean emitJSDoc) {
this.emitJSDoc = emitJSDoc;
}
@Override
public String apiDocFileFolder() {
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
}
@Override
public String toApiDocFilename(String name) {
return toApiName(name);
}
@Override
public String toModelDocFilename(String name) {
return toModelName(name);
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name);
name = sanitizeName(name); // FIXME parameter should not be assigned. Also declare it as "final"
if("_".equals(name)) {
name = "_u";
@ -241,7 +382,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
name = camelize(name, true);
// 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);
}
@ -256,16 +397,35 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
@Override
public String toModelName(String name) {
name = sanitizeName(name);
name = sanitizeName(name); // FIXME parameter should not be assigned. Also declare it as "final"
// model name cannot use reserved keyword, e.g. return
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// camelize the model name
// 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;
}
// model name starts with number
if (name.matches("^\\d.*")) {
String modelName = "Model" + name; // e.g. 200Response => Model200Response (after camelize)
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return name;
}
@Override
@ -289,58 +449,153 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
Property inner = ap.getItems();
return getSwaggerType(p); // TODO: + "/* <" + getTypeDeclaration(inner) + "> */";
return "[" + getTypeDeclaration(inner) + "]";
} else if (p instanceof MapProperty) {
MapProperty mp = (MapProperty) p;
Property inner = mp.getAdditionalProperties();
return getSwaggerType(p) + "<String, " + getTypeDeclaration(inner) + ">";
return "{String: " + getTypeDeclaration(inner) + "}";
}
return super.getTypeDeclaration(p);
}
@Override
public String toDefaultValue(Property p) {
if (p instanceof ArrayProperty) {
return "[]";
} else if (p instanceof MapProperty) {
return "{}";
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
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) {
LongProperty dp = (LongProperty) p;
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
public String toDefaultValueWithParam(String name, Property p) {
if (p instanceof ArrayProperty) {
return " = new Array();";
} else if (p instanceof MapProperty) {
return " = {}";
} else if (p instanceof LongProperty) {
LongProperty dp = (LongProperty) p;
return " = data." + name + ";";
// added for Javascript
} else if (p instanceof RefProperty) {
RefProperty rp = (RefProperty)p;
return ".constructFromObject(data." + name + ");";
String type = normalizeType(getTypeDeclaration(p));
if (p instanceof RefProperty) {
return " = " + type + ".constructFromObject(data['" + name + "']);";
} else {
return " = ApiClient.convertToType(data['" + name + "'], " + type + ");";
}
}
return super.toDefaultValueWithParam(name, p);
@Override
public void setParameterExampleValue(CodegenParameter p) {
String example;
if (p.defaultValue == null) {
example = p.example;
} else {
example = p.defaultValue;
}
String type = p.baseType;
if (type == null) {
type = p.dataType;
}
typeMapping.put("array", "Array");
typeMapping.put("List", "Array");
typeMapping.put("map", "Object");
typeMapping.put("object", "Object");
typeMapping.put("boolean", "Boolean");
typeMapping.put("char", "String");
typeMapping.put("string", "String");
typeMapping.put("short", "Integer");
typeMapping.put("int", "Integer");
typeMapping.put("integer", "Integer");
typeMapping.put("long", "Integer");
typeMapping.put("float", "Number");
typeMapping.put("double", "Number");
typeMapping.put("number", "Number");
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");
if ("String".equals(type)) {
if (example == null) {
example = p.paramName + "_example";
}
example = "\"" + escapeText(example) + "\"";
} else if ("Integer".equals(type)) {
if (example == null) {
example = "56";
}
} else if ("Number".equals(type)) {
if (example == null) {
example = "3.4";
}
} else if ("Boolean".equals(type)) {
if (example == null) {
example = "true";
}
} else if ("File".equals(type)) {
if (example == null) {
example = "/path/to/file";
}
example = "\"" + escapeText(example) + "\"";
} else if ("Date".equals(type)) {
if (example == null) {
example = "2013-10-20T19:20:30+01:00";
}
example = "new Date(\"" + escapeText(example) + "\")";
} else if (!languageSpecificPrimitives.contains(type)) {
// type is a model class, e.g. User
example = "new " + moduleName + "." + type + "()";
}
if (example == null) {
example = "null";
} else if (Boolean.TRUE.equals(p.isListContainer)) {
example = "[" + example + "]";
} else if (Boolean.TRUE.equals(p.isMapContainer)) {
example = "{key: " + example + "}";
}
p.example = example;
}
/**
* 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
public String getSwaggerType(Property p) {
@ -367,12 +622,51 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
throw new RuntimeException("Empty method/operation name (operationId) not allowed");
}
operationId = camelize(sanitizeName(operationId), true);
// 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");
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;
}
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);
}
// Set vendor-extension to be used in template:
// x-codegen-hasMoreRequired
// x-codegen-hasMoreOptional
// x-codegen-hasRequiredParams
CodegenParameter lastRequired = null;
CodegenParameter lastOptional = null;
for (CodegenParameter p : op.allParams) {
if (p.required != null && p.required) {
lastRequired = p;
} else {
lastOptional = p;
}
}
for (CodegenParameter p : op.allParams) {
if (p == lastRequired) {
p.vendorExtensions.put("x-codegen-hasMoreRequired", false);
} else if (p == lastOptional) {
p.vendorExtensions.put("x-codegen-hasMoreOptional", false);
} else {
p.vendorExtensions.put("x-codegen-hasMoreRequired", true);
p.vendorExtensions.put("x-codegen-hasMoreOptional", true);
}
}
op.vendorExtensions.put("x-codegen-hasRequiredParams", lastRequired != null);
return op;
}
@Override
@ -382,21 +676,162 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
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);
codegenModel = JavascriptClientCodegen.reconcileInlineEnums(codegenModel, parentCodegenModel);
}
return codegenModel;
}
private String trimBrackets(String s) {
if (s != null) {
int beginIdx = s.charAt(0) == '[' ? 1 : 0;
int endIdx = s.length();
if (s.charAt(endIdx - 1) == ']')
endIdx--;
return s.substring(beginIdx, endIdx);
}
return null;
}
private String getModelledType(String dataType) {
return "module:" + (StringUtils.isEmpty(modelPackage) ? "" : (modelPackage + "/")) + dataType;
}
private String getJSDocTypeWithBraces(CodegenModel cm, CodegenProperty cp) {
return "{" + getJSDocType(cm, cp) + "}";
}
private String getJSDocType(CodegenModel cm, CodegenProperty cp) {
if (Boolean.TRUE.equals(cp.isContainer)) {
if (cp.containerType.equals("array"))
return "Array.<" + getJSDocType(cm, cp.items) + ">";
else if (cp.containerType.equals("map"))
return "Object.<String, " + getJSDocType(cm, cp.items) + ">";
}
String dataType = trimBrackets(cp.datatypeWithEnum);
if (cp.isEnum) {
dataType = cm.classname + '.' + dataType;
}
if (isModelledType(cp))
dataType = getModelledType(dataType);
return dataType;
}
private boolean isModelledType(CodegenProperty cp) {
// N.B. enums count as modelled types, file is not modelled (SuperAgent uses some 3rd party library).
return cp.isEnum || !languageSpecificPrimitives.contains(cp.baseType == null ? cp.datatype : cp.baseType);
}
private String getJSDocTypeWithBraces(CodegenParameter cp) {
return "{" + getJSDocType(cp) + "}";
}
private String getJSDocType(CodegenParameter cp) {
String dataType = trimBrackets(cp.dataType);
if (isModelledType(cp))
dataType = getModelledType(dataType);
if (Boolean.TRUE.equals(cp.isListContainer)) {
return "Array.<" + dataType + ">";
} else if (Boolean.TRUE.equals(cp.isMapContainer)) {
return "Object.<String, " + dataType + ">";
}
return dataType;
}
private boolean isModelledType(CodegenParameter cp) {
// N.B. enums count as modelled types, file is not modelled (SuperAgent uses some 3rd party library).
return cp.isEnum || !languageSpecificPrimitives.contains(cp.baseType == null ? cp.dataType : cp.baseType);
}
private String getJSDocTypeWithBraces(CodegenOperation co) {
String jsDocType = getJSDocType(co);
return jsDocType == null ? null : "{" + jsDocType + "}";
}
private String getJSDocType(CodegenOperation co) {
String returnType = trimBrackets(co.returnType);
if (returnType != null) {
if (isModelledType(co))
returnType = getModelledType(returnType);
if (Boolean.TRUE.equals(co.isListContainer)) {
return "Array.<" + returnType + ">";
} else if (Boolean.TRUE.equals(co.isMapContainer)) {
return "Object.<String, " + returnType + ">";
}
}
return returnType;
}
private boolean isModelledType(CodegenOperation co) {
// This seems to be the only way to tell whether an operation return type is modelled.
return !Boolean.TRUE.equals(co.returnTypeIsPrimitive);
}
@SuppressWarnings("unchecked")
@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<String>();
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, ", "));
// Store JSDoc type specification into vendor-extension: x-jsdoc-type.
for (CodegenParameter cp : operation.allParams) {
String jsdocType = getJSDocTypeWithBraces(cp);
cp.vendorExtensions.put("x-jsdoc-type", jsdocType);
}
String jsdocType = getJSDocTypeWithBraces(operation);
operation.vendorExtensions.put("x-jsdoc-type", jsdocType);
}
}
return objs;
}
@SuppressWarnings("unchecked")
@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");
// Collect each model's required property names in *document order*.
// NOTE: can't use 'mandatory' as it is built from ModelImpl.getRequired(), which sorts names
// alphabetically and in any case the document order of 'required' and 'properties' can differ.
List<String> required = new ArrayList<String>();
List<String> allRequired = supportsInheritance ? new ArrayList<String>() : required;
cm.vendorExtensions.put("x-required", required);
cm.vendorExtensions.put("x-all-required", allRequired);
for (CodegenProperty var : cm.vars) {
Map<String, Object> allowableValues = var.allowableValues;
// Add JSDoc @type value for this property.
String jsDocType = getJSDocTypeWithBraces(cm, var);
var.vendorExtensions.put("x-jsdoc-type", jsDocType);
if (Boolean.TRUE.equals(var.required)) {
required.add(var.name);
}
// handle ArrayProperty
if (var.items != null) {
allowableValues = var.items.allowableValues;
@ -431,28 +866,27 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
}
allowableValues.put("enumVars", enumVars);
}
if (supportsInheritance) {
for (CodegenProperty var : cm.allVars) {
if (Boolean.TRUE.equals(var.required)) {
allRequired.add(var.name);
}
}
return objs;
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
if("retrofit".equals(getLibrary())) {
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.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;
// set vendor-extension: x-codegen-hasMoreRequired
CodegenProperty lastRequired = null;
for (CodegenProperty var : cm.vars) {
if (var.required != null && var.required) {
lastRequired = var;
}
}
}
if (operation.returnType == null) {
operation.returnType = "Void";
}
for (CodegenProperty var : cm.vars) {
if (var == lastRequired) {
var.vendorExtensions.put("x-codegen-hasMoreRequired", false);
} else if (var.required != null && var.required) {
var.vendorExtensions.put("x-codegen-hasMoreRequired", true);
}
}
}
@ -465,14 +899,14 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
&& !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()]));
// 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) {
private static String toEnumVarName(String value) {
String var = value.replaceAll("\\W+", "_").toUpperCase();
if (var.matches("\\d.*")) {
return "_" + var;
@ -481,7 +915,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
// 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
@ -529,7 +963,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
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.replaceAll("[^a-zA-Z0-9_\\.]", "_");
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,10 +8,11 @@ import com.fasterxml.jackson.databind.module.SimpleModule;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import io.swagger.codegen.*;
import io.swagger.models.Swagger;
import io.swagger.models.*;
import io.swagger.util.Yaml;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.IOException;
@ -20,6 +21,9 @@ import java.util.*;
import java.util.Map.Entry;
public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(NodeJSServerCodegen.class);
protected String apiVersion = "1.0.0";
protected int serverPort = 8080;
protected String projectName = "swagger-server";
@ -56,7 +60,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
/**
* Reserved words. Override this with reserved words specific to your language
*/
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
"break", "case", "class", "catch", "const", "continue", "debugger",
"default", "delete", "do", "else", "export", "extends", "finally",
@ -85,18 +89,9 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
"api",
"swagger.yaml")
);
supportingFiles.add(new SupportingFile("index.mustache",
"",
"index.js")
);
supportingFiles.add(new SupportingFile("package.mustache",
"",
"package.json")
);
supportingFiles.add(new SupportingFile("README.mustache",
"",
"README.md")
);
writeOptional(outputFolder, new SupportingFile("index.mustache", "", "index.js"));
writeOptional(outputFolder, new SupportingFile("package.mustache", "", "package.json"));
writeOptional(outputFolder, new SupportingFile("README.mustache", "", "README.md"));
if (System.getProperty("noservice") == null) {
apiTemplateFiles.put(
"service.mustache", // the template to use
@ -128,7 +123,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
*/
@Override
public String getName() {
return "nodejs";
return "nodejs-server";
}
/**
@ -184,6 +179,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
List<CodegenOperation> operations = (List<CodegenOperation>) objectMap.get("operation");
for (CodegenOperation operation : operations) {
operation.httpMethod = operation.httpMethod.toLowerCase();
List<CodegenParameter> params = operation.allParams;
if (params != null && params.size() == 0) {
operation.allParams = null;
@ -211,7 +207,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
}
@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>>();
Map<String, Object> apiInfo = (Map<String, Object>) objs.get("apiInfo");
List<Map<String, Object>> apis = (List<Map<String, Object>>) apiInfo.get("apis");
@ -221,7 +217,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
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();
for (CodegenOperation op : ops) {
@ -246,10 +242,6 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
@Override
public void preprocessSwagger(Swagger swagger) {
if ("/".equals(swagger.getBasePath())) {
swagger.setBasePath("");
}
String host = swagger.getHost();
String port = "8080";
if (host != null) {
@ -259,6 +251,40 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
}
}
this.additionalProperties.put("serverPort", port);
if (swagger.getInfo() != null) {
Info info = swagger.getInfo();
if (info.getTitle() != null) {
// when info.title is defined, use it for projectName
// used in package.json
projectName = dashize(info.getTitle());
this.additionalProperties.put("projectName", projectName);
}
}
// need vendor extensions for x-swagger-router-controller
Map<String, Path> paths = swagger.getPaths();
if(paths != null) {
for(String pathname : paths.keySet()) {
Path path = paths.get(pathname);
Map<HttpMethod, Operation> operationMap = path.getOperationMap();
if(operationMap != null) {
for(HttpMethod method : operationMap.keySet()) {
Operation operation = operationMap.get(method);
String tag = "default";
if(operation.getTags() != null && operation.getTags().size() > 0) {
tag = toApiName(operation.getTags().get(0));
}
if(operation.getOperationId() == null) {
operation.setOperationId(getOrGenerateOperationId(operation, pathname, method.toString()));
}
if(operation.getVendorExtensions().get("x-swagger-router-controller") == null) {
operation.getVendorExtensions().put("x-swagger-router-controller", sanitizeTag(tag));
}
}
}
}
}
}
@Override
@ -276,7 +302,7 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
});
objs.put("swagger-yaml", Yaml.mapper().registerModule(module).writeValueAsString(swagger));
} catch (JsonProcessingException e) {
e.printStackTrace();
LOGGER.error(e.getMessage(), e);
}
}
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.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
@ -13,6 +14,8 @@ import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
@ -84,15 +87,18 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("List", "NSArray");
typeMapping.put("object", "NSObject");
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
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
// local variable names in API methods (endpoints)
"resourcePath", "pathParams", "queryParams", "headerParams",
"responseContentType", "requestContentType", "authSettings",
"formParams", "files", "bodyParam",
"formParams", "localVarFiles", "bodyParam",
// objc reserved words
"auto", "else", "long", "switch",
"break", "enum", "register", "typedef",
@ -214,17 +220,17 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("Configuration-header.mustache", swaggerFolder, classPrefix + "Configuration.h"));
supportingFiles.add(new SupportingFile("podspec.mustache", "", podName + ".podspec"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
}
@Override
public String toInstantiationType(Property p) {
if (p instanceof MapProperty) {
MapProperty ap = (MapProperty) p;
String inner = getSwaggerType(ap.getAdditionalProperties());
return instantiationTypes.get("map");
} else if (p instanceof ArrayProperty) {
ArrayProperty ap = (ArrayProperty) p;
String inner = getSwaggerType(ap.getItems());
return instantiationTypes.get("array");
} else {
return null;
@ -247,12 +253,12 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type) && !foundationClasses.contains(type)) {
return toModelName(type);
return toModelNameWithoutReservedWordCheck(type);
}
} else {
type = swaggerType;
}
return toModelName(type);
return toModelNameWithoutReservedWordCheck(type);
}
@Override
@ -312,7 +318,32 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
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)
}
// model name starts with number
/* no need for the fix below as objc model starts with prefix (e.g. SWG)
if (type.matches("^\\d.*")) {
LOGGER.warn(type + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + type));
type = "model_" + type; // e.g. 200Response => Model200Response (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
if (typeMapping.keySet().contains(type) ||
@ -324,7 +355,15 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
}
// custom classes
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 +411,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toVarName(String 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 (name.matches("^[A-Z_]$")) {
@ -390,7 +429,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
name = camelize(name, true);
// 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);
}
@ -409,6 +448,7 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return "_" + name;
}
@SuppressWarnings("static-method")
public String escapeSpecialWord(String name) {
return "var_" + name;
}
@ -421,8 +461,9 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
}
// 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");
if (isReservedWord(operationId)) {
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);
@ -456,6 +497,21 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
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
*

View File

@ -1,27 +1,44 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenParameter;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CliOption;
import io.swagger.models.properties.ArrayProperty;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.StringProperty;
import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.IntegerProperty;
import io.swagger.models.properties.FloatProperty;
import io.swagger.models.properties.DoubleProperty;
import io.swagger.models.properties.BooleanProperty;
import io.swagger.models.properties.BinaryProperty;
import io.swagger.models.properties.ByteArrayProperty;
import io.swagger.models.properties.DateTimeProperty;
import io.swagger.models.properties.DateProperty;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.regex.Matcher;
import org.apache.commons.lang.StringUtils;
public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
public static final String MODULE_NAME = "moduleName";
public static final String MODULE_VERSION = "moduleVersion";
protected String moduleName = "SwaggerClient";
protected String moduleName = "WWW::SwaggerClient";
protected String modulePathPart = moduleName.replaceAll("::", Matcher.quoteReplacement(File.separator));
protected String moduleVersion = "1.0.0";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
protected static int emptyFunctionNameCounter = 0;
public PerlClientCodegen() {
super();
@ -29,10 +46,14 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
outputFolder = "generated-code" + File.separatorChar + "perl";
modelTemplateFiles.put("object.mustache", ".pm");
apiTemplateFiles.put("api.mustache", ".pm");
modelTestTemplateFiles.put("object_test.mustache", ".t");
apiTestTemplateFiles.put("api_test.mustache", ".t");
modelDocTemplateFiles.put("object_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
embeddedTemplateDir = templateDir = "perl";
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
"else", "lock", "qw",
"__END__", "elsif", "lt", "qx",
@ -43,7 +64,8 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
"cmp", "ge", "package", "until",
"continue", "gt", "q", "while",
"CORE", "if", "qq", "xor",
"do", "le", "qr", "y"
"do", "le", "qr", "y",
"return"
)
);
@ -70,9 +92,12 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("array", "ARRAY");
typeMapping.put("map", "HASH");
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.add(new CliOption(MODULE_NAME, "Perl module name (convention: CamelCase).").defaultValue("SwaggerClient"));
cliOptions.add(new CliOption(MODULE_NAME, "Perl module name (convention: CamelCase or Long::Module).").defaultValue("SwaggerClient"));
cliOptions.add(new CliOption(MODULE_VERSION, "Perl module version.").defaultValue("1.0.0"));
cliOptions.add(CliOption.newBoolean(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue(Boolean.TRUE.toString()));
@ -94,17 +119,24 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
if (additionalProperties.containsKey(MODULE_NAME)) {
setModuleName((String) additionalProperties.get(MODULE_NAME));
setModulePathPart(moduleName.replaceAll("::", Matcher.quoteReplacement(File.separator)));
} else {
additionalProperties.put(MODULE_NAME, moduleName);
}
supportingFiles.add(new SupportingFile("ApiClient.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "ApiClient.pm"));
supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "Configuration.pm"));
supportingFiles.add(new SupportingFile("ApiFactory.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "ApiFactory.pm"));
supportingFiles.add(new SupportingFile("Role.mustache", ("lib/WWW/" + moduleName).replace('/', File.separatorChar), "Role.pm"));
supportingFiles.add(new SupportingFile("AutoDoc.mustache", ("lib/WWW/" + moduleName + "/Role").replace('/', File.separatorChar), "AutoDoc.pm"));
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
supportingFiles.add(new SupportingFile("ApiClient.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "ApiClient.pm"));
supportingFiles.add(new SupportingFile("Configuration.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "Configuration.pm"));
supportingFiles.add(new SupportingFile("ApiFactory.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "ApiFactory.pm"));
supportingFiles.add(new SupportingFile("Role.mustache", ("lib/" + modulePathPart).replace('/', File.separatorChar), "Role.pm"));
supportingFiles.add(new SupportingFile("AutoDoc.mustache", ("lib/" + modulePathPart + "/Role").replace('/', File.separatorChar), "AutoDoc.pm"));
supportingFiles.add(new SupportingFile("autodoc.script.mustache", "bin", "autodoc"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
}
@Override
@ -129,12 +161,32 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String apiFileFolder() {
return (outputFolder + "/lib/WWW/" + moduleName + apiPackage()).replace('/', File.separatorChar);
return (outputFolder + "/lib/" + modulePathPart + apiPackage()).replace('/', File.separatorChar);
}
@Override
public String modelFileFolder() {
return (outputFolder + "/lib/WWW/" + moduleName + modelPackage()).replace('/', File.separatorChar);
return (outputFolder + "/lib/" + modulePathPart + modelPackage()).replace('/', File.separatorChar);
}
@Override
public String apiTestFileFolder() {
return (outputFolder + "/t").replace('/', File.separatorChar);
}
@Override
public String modelTestFileFolder() {
return (outputFolder + "/t").replace('/', File.separatorChar);
}
@Override
public String apiDocFileFolder() {
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
}
@Override
@ -166,12 +218,48 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
if (type == null) {
return null;
}
return type;
return toModelName(type);
}
@Override
public String toDefaultValue(Property p) {
return "null";
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;
}
@ -179,14 +267,13 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
public String toVarName(String name) {
// return the name in underscore style
// 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
// need to escape it by appending _ at the beginning
if (name.matches("^\\d.*")) {
name = "_" + name;
}
return name;
}
@ -198,9 +285,27 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
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
if (reservedWords.contains(name)) {
escapeReservedWord(name); // e.g. return => _return
if (isReservedWord(name)) {
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name;
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
// add prefix/suffic to model name
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// camelize the model name
@ -214,10 +319,30 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
return toModelName(name);
}
@Override
public String toModelTestFilename(String name) {
return toModelFilename(name) + "Test";
}
@Override
public String toModelDocFilename(String name) {
return toModelFilename(name);
}
@Override
public String toApiTestFilename(String name) {
return toApiFilename(name) + "Test";
}
@Override
public String toApiDocFilename(String name) {
return toApiFilename(name);
}
@Override
public String toApiFilename(String name) {
// 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
return camelize(name) + "Api";
@ -234,14 +359,17 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
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)) {
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
if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
if (isReservedWord(operationId)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore("call_" + operationId));
return underscore("call_" + operationId);
}
return underscore(operationId);
@ -251,7 +379,27 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
this.moduleName = moduleName;
}
public void setModulePathPart(String modulePathPart) {
this.modulePathPart = modulePathPart;
}
public void setModuleVersion(String moduleVersion) {
this.moduleVersion = moduleVersion;
}
@Override
public void setParameterExampleValue(CodegenParameter p) {
if (Boolean.TRUE.equals(p.isString) || Boolean.TRUE.equals(p.isBinary) ||
Boolean.TRUE.equals(p.isByteArray) || Boolean.TRUE.equals(p.isFile)) {
p.example = "'" + p.example + "'";
} else if (Boolean.TRUE.equals(p.isBoolean)) {
if (Boolean.parseBoolean(p.example))
p.example = new String("1");
else
p.example = new String("0");
} else if (Boolean.TRUE.equals(p.isDateTime) || Boolean.TRUE.equals(p.isDate)) {
p.example = "DateTime->from_epoch(epoch => str2time('" + p.example + "'))";
}
}
}

View File

@ -3,6 +3,7 @@ package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenParameter;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
@ -20,6 +21,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@SuppressWarnings("hiding")
static Logger LOGGER = LoggerFactory.getLogger(PhpClientCodegen.class);
public static final String VARIABLE_NAMING_CONVENTION = "variableNamingConvention";
@ -34,21 +36,30 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String artifactVersion = "1.0.0";
protected String srcBasePath = "lib";
protected String variableNamingConvention= "snake_case";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
public PhpClientCodegen() {
super();
supportsInheritance = true;
outputFolder = "generated-code" + File.separator + "php";
modelTemplateFiles.put("model.mustache", ".php");
apiTemplateFiles.put("api.mustache", ".php");
modelTestTemplateFiles.put("model_test.mustache", ".php");
apiTestTemplateFiles.put("api_test.mustache", ".php");
embeddedTemplateDir = templateDir = "php";
apiPackage = invokerPackage + "\\Api";
modelPackage = invokerPackage + "\\Model";
testPackage = invokerPackage + "\\Tests";
reservedWords = new HashSet<String>(
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
setReservedWordsLowerCase(
Arrays.asList(
// local variables used in api methods (endpoints)
"resourcePath", "method", "httpBody", "queryParams", "headerParams",
"resourcePath", "httpBody", "queryParams", "headerParams",
"formParams", "_header_accept", "_tempBody",
// PHP reserved words
@ -97,6 +108,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("array", "array");
typeMapping.put("list", "array");
typeMapping.put("object", "object");
typeMapping.put("binary", "string");
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
@ -105,8 +117,8 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(new CliOption(CodegenConstants.INVOKER_PACKAGE, "The main namespace to use for all classes. e.g. Yay\\Pets"));
cliOptions.add(new CliOption(PACKAGE_PATH, "The main package name for classes. e.g. GeneratedPetstore"));
cliOptions.add(new CliOption(SRC_BASE_PATH, "The directory under packagePath to serve as source root."));
cliOptions.add(new CliOption(COMPOSER_VENDOR_NAME, "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. yaypets"));
cliOptions.add(new CliOption(COMPOSER_PROJECT_NAME, "The project name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. petstore-client"));
cliOptions.add(new CliOption(COMPOSER_VENDOR_NAME, "The vendor name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. yaypets. IMPORTANT NOTE (2016/03): composerVendorName will be deprecated and replaced by gitUserId in the next swagger-codegen release"));
cliOptions.add(new CliOption(COMPOSER_PROJECT_NAME, "The project name used in the composer package name. The template uses {{composerVendorName}}/{{composerProjectName}} for the composer package name. e.g. petstore-client. IMPORTANT NOTE (2016/03): composerProjectName will be deprecated and replaced by gitRepoId in the next swagger-codegen release"));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_VERSION, "The version to use in the composer package version field. e.g. 1.2.3"));
}
@ -115,9 +127,9 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
}
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) {
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;
@ -212,12 +224,20 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\"));
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
supportingFiles.add(new SupportingFile("configuration.mustache", toPackagePath(invokerPackage, srcBasePath), "Configuration.php"));
supportingFiles.add(new SupportingFile("ApiClient.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiClient.php"));
supportingFiles.add(new SupportingFile("ApiException.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiException.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("autoload.mustache", getPackagePath(), "autoload.php"));
supportingFiles.add(new SupportingFile("README.mustache", getPackagePath(), "README.md"));
supportingFiles.add(new SupportingFile(".travis.yml", getPackagePath(), ".travis.yml"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", getPackagePath(), "git_push.sh"));
}
@Override
@ -235,6 +255,38 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return (outputFolder + "/" + toPackagePath(modelPackage, srcBasePath));
}
@Override
public String apiTestFileFolder() {
return (outputFolder + "/" + toPackagePath(testPackage, srcBasePath));
}
@Override
public String modelTestFileFolder() {
return (outputFolder + "/" + toPackagePath(testPackage, srcBasePath));
}
@Override
public String apiDocFileFolder() {
//return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
return (outputFolder + "/" + getPackagePath() + "/" + apiDocPath);
}
@Override
public String modelDocFileFolder() {
//return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
return (outputFolder + "/" + getPackagePath() + "/" + modelDocPath);
}
@Override
public String toModelDocFilename(String name) {
return toModelName(name);
}
@Override
public String toApiDocFilename(String name) {
return toApiName(name);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
@ -312,7 +364,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toVarName(String 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)) {
// return the name in camelCase style
@ -341,15 +393,30 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toModelName(String name) {
// remove [
name = name.replaceAll("\\]", "");
// 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
name = name.replaceAll("$", "");
// model name cannot use reserved keyword
if (reservedWords.contains(name)) {
escapeReservedWord(name); // e.g. return => _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)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (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
@ -363,6 +430,12 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return toModelName(name);
}
@Override
public String toModelTestFilename(String name) {
// should be the same as the model name
return toModelName(name) + "Test";
}
@Override
public String toOperationId(String operationId) {
// throw exception if method name is empty
@ -371,8 +444,9 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
}
// 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");
if (isReservedWord(operationId)) {
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);
@ -425,4 +499,69 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
return null;
}
@Override
public void setParameterExampleValue(CodegenParameter p) {
String example;
if (p.defaultValue == null) {
example = p.example;
} else {
example = p.defaultValue;
}
String type = p.baseType;
if (type == null) {
type = p.dataType;
}
if ("String".equalsIgnoreCase(type)) {
if (example == null) {
example = p.paramName + "_example";
}
example = "\"" + escapeText(example) + "\"";
} else if ("Integer".equals(type) || "int".equals(type)) {
if (example == null) {
example = "56";
}
} else if ("Float".equalsIgnoreCase(type) || "Double".equalsIgnoreCase(type)) {
if (example == null) {
example = "3.4";
}
} else if ("BOOLEAN".equalsIgnoreCase(type) || "bool".equalsIgnoreCase(type)) {
if (example == null) {
example = "True";
}
} else if ("\\SplFileObject".equalsIgnoreCase(type)) {
if (example == null) {
example = "/path/to/file";
}
example = "\"" + escapeText(example) + "\"";
} else if ("Date".equalsIgnoreCase(type)) {
if (example == null) {
example = "2013-10-20";
}
example = "new \\DateTime(\"" + escapeText(example) + "\")";
} else if ("DateTime".equalsIgnoreCase(type)) {
if (example == null) {
example = "2013-10-20T19:20:30+01:00";
}
example = "new \\DateTime(\"" + escapeText(example) + "\")";
} else if (!languageSpecificPrimitives.contains(type)) {
// type is a model class, e.g. User
example = "new " + type + "()";
} else {
LOGGER.warn("Type " + type + " not handled properly in setParameterExampleValue");
}
if (example == null) {
example = "NULL";
} else if (Boolean.TRUE.equals(p.isListContainer)) {
example = "array(" + example + ")";
} else if (Boolean.TRUE.equals(p.isMapContainer)) {
example = "array('key' => " + example + ")";
}
p.example = example;
}
}

View File

@ -51,13 +51,16 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("DateTime", "datetime");
typeMapping.put("object", "object");
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
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
// local variable name used in API methods (endpoints)
"all_params", "resource_path", "method", "path_params", "query_params",
"header_params", "form_params", "files", "body_params", "auth_settings",
"all_params", "resource_path", "path_params", "query_params",
"header_params", "form_params", "local_var_files", "body_params", "auth_settings",
// python reserved words
"and", "del", "from", "not", "while", "as", "elif", "global", "or", "with",
"assert", "else", "if", "pass", "yield", "break", "except", "import",
@ -107,6 +110,8 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
supportingFiles.add(new SupportingFile("__init__package.mustache", swaggerFolder, "__init__.py"));
supportingFiles.add(new SupportingFile("__init__model.mustache", modelPackage, "__init__.py"));
supportingFiles.add(new SupportingFile("__init__api.mustache", apiPackage, "__init__.py"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
}
private static String dropDots(String str) {
@ -176,7 +181,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
public String toVarName(String 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
name = name.replaceAll("$", "");
@ -194,7 +199,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
name = name.replaceAll("^_*", "");
// 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);
}
@ -209,14 +214,28 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
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
name = name.replaceAll("$", "");
// 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");
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)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// camelize the model name
@ -226,9 +245,28 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
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
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
if (isReservedWord(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)
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + underscore("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
// underscore the model file name
@ -264,14 +302,15 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
@Override
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)) {
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");
if (isReservedWord(operationId)) {
LOGGER.warn(operationId + " (reserved word) cannot be used as method name. Renamed to " + underscore(sanitizeName("call_" + operationId)));
operationId = "call_" + operationId;
}
return underscore(sanitizeName(operationId));
@ -290,7 +329,11 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
*
* (PEP 0008) Python packages should also have short, all-lowercase names,
* 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) {
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
*/
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
"sample1", // replace with static values
"sample2")
@ -121,6 +121,9 @@ public class Qt5CPPGenerator extends DefaultCodegen implements CodegenConfig {
typeMapping.put("map", "QMap");
typeMapping.put("file", "SWGHttpRequestInputFileElement");
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>();

View File

@ -3,26 +3,53 @@ package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
import io.swagger.codegen.CodegenParameter;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Model;
import io.swagger.models.Operation;
import io.swagger.models.Swagger;
import io.swagger.models.properties.*;
import java.io.File;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 MODULE_NAME = "moduleName";
public static final String GEM_VERSION = "gemVersion";
public static final String GEM_LICENSE = "gemLicense";
public static final String GEM_HOMEPAGE = "gemHomepage";
public static final String GEM_SUMMARY = "gemSummary";
public static final String GEM_DESCRIPTION = "gemDescription";
public static final String GEM_AUTHOR = "gemAuthor";
public static final String GEM_AUTHOR_EMAIL = "gemAuthorEmail";
protected String gemName;
protected String moduleName;
protected String gemVersion = "1.0.0";
protected String specFolder = "spec";
protected String libFolder = "lib";
protected String gemLicense = "Apache-2.0";
protected String gemHomepage = "http://swagger.io";
protected String gemSummary = "A ruby wrapper for the swagger APIs";
protected String gemDescription = "This gem maps to a swagger API";
protected String gemAuthor = "";
protected String gemAuthorEmail = "";
protected String apiDocPath = "docs/";
protected String modelDocPath = "docs/";
protected static int emptyMethodNameCounter = 0;
public RubyClientCodegen() {
super();
@ -31,15 +58,17 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
outputFolder = "generated-code" + File.separator + "ruby";
modelTemplateFiles.put("model.mustache", ".rb");
apiTemplateFiles.put("api.mustache", ".rb");
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
embeddedTemplateDir = templateDir = "ruby";
typeMapping.clear();
languageSpecificPrimitives.clear();
modelTestTemplateFiles.put("model_test.mustache", ".rb");
apiTestTemplateFiles.put("api_test.mustache", ".rb");
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
// 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",
// ruby reserved keywords
"__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__",
@ -49,11 +78,25 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
"if", "not", "return", "undef", "yield")
);
typeMapping.clear();
languageSpecificPrimitives.clear();
// primitives in ruby lang
languageSpecificPrimitives.add("int");
languageSpecificPrimitives.add("array");
languageSpecificPrimitives.add("map");
languageSpecificPrimitives.add("string");
// primitives in the typeMapping
languageSpecificPrimitives.add("String");
languageSpecificPrimitives.add("Integer");
languageSpecificPrimitives.add("Float");
languageSpecificPrimitives.add("Date");
languageSpecificPrimitives.add("DateTime");
languageSpecificPrimitives.add("BOOLEAN");
languageSpecificPrimitives.add("Array");
languageSpecificPrimitives.add("Hash");
languageSpecificPrimitives.add("File");
languageSpecificPrimitives.add("Object");
typeMapping.put("string", "String");
typeMapping.put("char", "String");
@ -72,6 +115,7 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("map", "Hash");
typeMapping.put("object", "Object");
typeMapping.put("file", "File");
typeMapping.put("binary", "String");
// remove modelPackage and apiPackage added by default
Iterator<CliOption> itr = cliOptions.iterator();
@ -87,6 +131,23 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
cliOptions.add(new CliOption(MODULE_NAME, "top module name (convention: CamelCase, usually corresponding" +
" to gem name).").defaultValue("SwaggerClient"));
cliOptions.add(new CliOption(GEM_VERSION, "gem version.").defaultValue("1.0.0"));
cliOptions.add(new CliOption(GEM_LICENSE, "gem license. ").
defaultValue("Apache-2.0"));
cliOptions.add(new CliOption(GEM_HOMEPAGE, "gem homepage. ").
defaultValue("http://swagger.io"));
cliOptions.add(new CliOption(GEM_SUMMARY, "gem summary. ").
defaultValue("A ruby wrapper for the swagger APIs"));
cliOptions.add(new CliOption(GEM_DESCRIPTION, "gem description. ").
defaultValue("This gem maps to a swagger API"));
cliOptions.add(new CliOption(GEM_AUTHOR, "gem author (only one is supported)."));
cliOptions.add(new CliOption(GEM_AUTHOR_EMAIL, "gem author email (only one is supported)."));
}
@Override
@ -114,11 +175,39 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
if (additionalProperties.containsKey(GEM_VERSION)) {
setGemVersion((String) additionalProperties.get(GEM_VERSION));
} else {
}else {
// not set, pass the default value to template
additionalProperties.put(GEM_VERSION, gemVersion);
}
if (additionalProperties.containsKey(GEM_LICENSE)) {
setGemLicense((String) additionalProperties.get(GEM_LICENSE));
}
if (additionalProperties.containsKey(GEM_HOMEPAGE)) {
setGemHomepage((String) additionalProperties.get(GEM_HOMEPAGE));
}
if (additionalProperties.containsKey(GEM_SUMMARY)) {
setGemSummary((String) additionalProperties.get(GEM_SUMMARY));
}
if (additionalProperties.containsKey(GEM_DESCRIPTION)) {
setGemDescription((String) additionalProperties.get(GEM_DESCRIPTION));
}
if (additionalProperties.containsKey(GEM_AUTHOR)) {
setGemAuthor((String) additionalProperties.get(GEM_AUTHOR));
}
if (additionalProperties.containsKey(GEM_AUTHOR_EMAIL)) {
setGemAuthorEmail((String) additionalProperties.get(GEM_AUTHOR_EMAIL));
}
// make api and model doc path available in mustache template
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
// use constant model/api package (folder path)
setModelPackage("models");
setApiPackage("api");
@ -130,7 +219,39 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
supportingFiles.add(new SupportingFile("api_error.mustache", gemFolder, "api_error.rb"));
supportingFiles.add(new SupportingFile("configuration.mustache", gemFolder, "configuration.rb"));
supportingFiles.add(new SupportingFile("version.mustache", gemFolder, "version.rb"));
String modelFolder = gemFolder + File.separator + modelPackage.replace("/", File.separator);
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
}
@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);
// Set vendor-extension to be used in template:
// x-codegen-hasMoreRequired
// x-codegen-hasMoreOptional
// x-codegen-hasRequiredParams
CodegenParameter lastRequired = null;
CodegenParameter lastOptional = null;
for (CodegenParameter p : op.allParams) {
if (p.required != null && p.required) {
lastRequired = p;
} else {
lastOptional = p;
}
}
for (CodegenParameter p : op.allParams) {
if (p == lastRequired) {
p.vendorExtensions.put("x-codegen-hasMoreRequired", false);
} else if (p == lastOptional) {
p.vendorExtensions.put("x-codegen-hasMoreOptional", false);
} else {
p.vendorExtensions.put("x-codegen-hasMoreRequired", true);
p.vendorExtensions.put("x-codegen-hasMoreOptional", true);
}
}
op.vendorExtensions.put("x-codegen-hasRequiredParams", lastRequired != null);
return op;
}
@Override
@ -150,14 +271,22 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
/**
* 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) {
return camelize(gemName.replaceAll("[^\\w]+", "_"));
}
/**
* 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) {
return underscore(moduleName.replaceAll("[^\\w]+", ""));
}
@ -177,6 +306,26 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
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
public String apiDocFileFolder() {
return (outputFolder + "/" + apiDocPath).replace('/', File.separatorChar);
}
@Override
public String modelDocFileFolder() {
return (outputFolder + "/" + modelDocPath).replace('/', File.separatorChar);
}
@Override
public String getTypeDeclaration(Property p) {
if (p instanceof ArrayProperty) {
@ -243,14 +392,13 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
if (type == null) {
return null;
}
return type;
return toModelName(type);
}
@Override
public String toVarName(String 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 (name.matches("^[A-Z_]*$")) {
name = name.toLowerCase();
@ -261,7 +409,7 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
name = underscore(name);
// 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);
}
@ -276,11 +424,27 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
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
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
if (isReservedWord(name)) {
String modelName = camelize("Model" + name);
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. 200Response => Model200Response (after camelize)
}
// camelize the model name
@ -290,9 +454,26 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
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
if (reservedWords.contains(name)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
if (isReservedWord(name)) {
String filename = underscore("model_" + name);
LOGGER.warn(name + " (reserved word) cannot be used as model filename. Renamed to " + filename);
return filename;
}
// model name starts with number
if (name.matches("^\\d.*")) {
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + underscore("model_" + name));
name = "model_" + name; // e.g. 200Response => model_200_response
}
// underscore the model file name
@ -300,15 +481,35 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
return underscore(name);
}
@Override
public String toModelDocFilename(String name) {
return toModelName(name);
}
@Override
public String toApiFilename(String name) {
// 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
return underscore(name) + "_api";
}
@Override
public String toApiDocFilename(String name) {
return toApiName(name);
}
@Override
public String toApiTestFilename(String name) {
return toApiFilename(name) + "_spec";
}
@Override
public String toModelTestFilename(String name) {
return toModelFilename(name) + "_spec";
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
@ -320,27 +521,89 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
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)) {
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
if (reservedWords.contains(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
if (isReservedWord(operationId)) {
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));
}
@Override
public String toModelImport(String name) {
return gemName + "/" + modelPackage() + "/" + toModelFilename(name);
public String toApiImport(String name) {
return gemName + "/" + apiPackage() + "/" + toApiFilename(name);
}
@Override
public String toApiImport(String name) {
return gemName + "/" + apiPackage() + "/" + toApiFilename(name);
public void setParameterExampleValue(CodegenParameter p) {
String example;
if (p.defaultValue == null) {
example = p.example;
} else {
example = p.defaultValue;
}
String type = p.baseType;
if (type == null) {
type = p.dataType;
}
if ("String".equals(type)) {
if (example == null) {
example = p.paramName + "_example";
}
example = "\"" + escapeText(example) + "\"";
} else if ("Integer".equals(type)) {
if (example == null) {
example = "56";
}
} else if ("Float".equals(type)) {
if (example == null) {
example = "3.4";
}
} else if ("BOOLEAN".equals(type)) {
if (example == null) {
example = "true";
}
} else if ("File".equals(type)) {
if (example == null) {
example = "/path/to/file";
}
example = "File.new(\"" + escapeText(example) + "\")";
} else if ("Date".equals(type)) {
if (example == null) {
example = "2013-10-20";
}
example = "Date.parse(\"" + escapeText(example) + "\")";
} else if ("DateTime".equals(type)) {
if (example == null) {
example = "2013-10-20T19:20:30+01:00";
}
example = "DateTime.parse(\"" + escapeText(example) + "\")";
} else if (!languageSpecificPrimitives.contains(type)) {
// type is a model class, e.g. User
example = moduleName + "::" + type + ".new";
}
if (example == null) {
example = "nil";
} else if (Boolean.TRUE.equals(p.isListContainer)) {
example = "[" + example + "]";
} else if (Boolean.TRUE.equals(p.isMapContainer)) {
example = "{'key' => " + example + "}";
}
p.example = example;
}
public void setGemName(String gemName) {
@ -354,4 +617,28 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
public void setGemVersion(String gemVersion) {
this.gemVersion = gemVersion;
}
public void setGemDescription(String gemDescription) {
this.gemDescription = gemDescription;
}
public void setGemSummary(String gemSummary) {
this.gemSummary = gemSummary;
}
public void setGemLicense(String gemLicense) {
this.gemLicense = gemLicense;
}
public void setGemHomepage(String gemHomepage) {
this.gemHomepage = gemHomepage;
}
public void setGemAuthor(String gemAuthor) {
this.gemAuthor = gemAuthor;
}
public void setGemAuthorEmail(String gemAuthorEmail) {
this.gemAuthorEmail = gemAuthorEmail;
}
}

View File

@ -47,8 +47,13 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
apiPackage = "io.swagger.client.api";
modelPackage = "io.swagger.client.model";
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
// local variable names used in API methods (endpoints)
"path", "contentTypes", "contentType", "queryParams", "headerParams",
"formParams", "postBody", "mp", "basePath", "apiInvoker",
// scala reserved words
"abstract", "case", "catch", "class", "def", "do", "else", "extends",
"false", "final", "finally", "for", "forSome", "if", "implicit",
"import", "lazy", "match", "new", "null", "object", "override", "package",
@ -67,6 +72,8 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("apiInvoker.mustache",
(sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiInvoker.scala"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
importMapping.remove("List");
importMapping.remove("Set");
@ -91,6 +98,9 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("double", "Double");
typeMapping.put("object", "Any");
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>(
Arrays.asList(
@ -102,6 +112,7 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
"Long",
"Float",
"Object",
"Any",
"List",
"Map")
);
@ -227,7 +238,7 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
}
// 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");
}
@ -247,4 +258,67 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig
return objs;
}
@Override
public String toVarName(String name) {
// sanitize name
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
if("_".equals(name)) {
name = "_u";
}
// 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, 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(final String name) {
final String sanitizedName = sanitizeName(modelNamePrefix + name + modelNameSuffix);
// camelize the model name
// phone_number => PhoneNumber
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;
}
// model name starts with number
if (name.matches("^\\d.*")) {
final String modelName = "Model" + camelizedName; // e.g. 200Response => Model200Response (after camelize)
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return camelizedName;
}
@Override
public String toModelFilename(String name) {
// should be the same as the model name
return toModelName(name);
}
}

View File

@ -34,7 +34,7 @@ public class ScalatraServerCodegen extends DefaultCodegen implements CodegenConf
apiPackage = "com.wordnik.client.api";
modelPackage = "com.wordnik.client.model";
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
"abstract", "continue", "for", "new", "switch", "assert",
"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("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");

View File

@ -37,7 +37,7 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
embeddedTemplateDir = templateDir = "silex";
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
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")
);
@ -81,6 +81,9 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
typeMapping.put("array", "array");
typeMapping.put("list", "array");
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("composer.json", packagePath.replace('/', File.separatorChar), "composer.json"));
@ -162,7 +165,7 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
public String toVarName(String name) {
// return the name in underscore style
// 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
// need to escape it by appending _ at the beginning
@ -182,7 +185,7 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
@Override
public String toModelName(String name) {
// model name cannot use reserved keyword
if (reservedWords.contains(name)) {
if (isReservedWord(name)) {
escapeReservedWord(name); // e.g. return => _return
}

View File

@ -2,7 +2,6 @@ package io.swagger.codegen.languages;
import com.fasterxml.jackson.core.JsonProcessingException;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.DefaultCodegen;
@ -19,8 +18,13 @@ import java.util.HashSet;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(SinatraServerCodegen.class);
protected String gemName;
protected String moduleName;
protected String gemVersion = "1.0.0";
@ -39,7 +43,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
typeMapping.clear();
languageSpecificPrimitives.clear();
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
Arrays.asList(
"__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__",
"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("List", "array");
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
cliOptions.clear();
@ -146,7 +153,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
@Override
public String toVarName(String name) {
// 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 (name.matches("^[A-Z_]*$")) {
@ -158,7 +165,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
name = underscore(name);
// 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);
}
@ -174,7 +181,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
@Override
public String toModelName(String name) {
// 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");
}
@ -186,7 +193,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
@Override
public String toModelFilename(String name) {
// 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");
}
@ -198,7 +205,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
@Override
public String toApiFilename(String name) {
// 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
return underscore(name) + "_api";
@ -216,7 +223,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
@Override
public String toOperationId(String operationId) {
// 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");
}
@ -230,7 +237,7 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
try {
objs.put("swagger-yaml", Yaml.mapper().writeValueAsString(swagger));
} catch (JsonProcessingException e) {
e.printStackTrace();
LOGGER.error(e.getMessage(), e);
}
}
return super.postProcessSupportingFileData(objs);

View File

@ -39,7 +39,7 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
embeddedTemplateDir = templateDir = "slim";
reservedWords = new HashSet<String>(
setReservedWordsLowerCase(
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")
);
@ -83,6 +83,9 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
typeMapping.put("array", "array");
typeMapping.put("list", "array");
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("composer.json", packagePath.replace('/', File.separatorChar), "composer.json"));
@ -177,8 +180,7 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
@Override
public String toVarName(String 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)) {
// return the name in camelCase style
@ -208,7 +210,7 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
@Override
public String toModelName(String name) {
// model name cannot use reserved keyword
if (reservedWords.contains(name)) {
if (isReservedWord(name)) {
escapeReservedWord(name); // e.g. return => _return
}

View File

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

View File

@ -1,5 +1,6 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenType;
@ -22,6 +23,11 @@ public class StaticDocCodegen extends DefaultCodegen implements CodegenConfig {
apiTemplateFiles.put("operation.mustache", ".html");
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.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);

View File

@ -1,5 +1,6 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenConfig;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenOperation;
@ -32,6 +33,17 @@ public class StaticHtmlGenerator extends DefaultCodegen implements CodegenConfig
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("appDescription", "A sample swagger server");
additionalProperties.put("infoUrl", "https://helloreverb.com");
@ -89,20 +101,4 @@ public class StaticHtmlGenerator extends DefaultCodegen implements CodegenConfig
}
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;
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.CodegenType;
import io.swagger.codegen.DefaultCodegen;
import io.swagger.codegen.SupportingFile;
import io.swagger.models.Swagger;
import io.swagger.util.Json;
import org.apache.commons.io.FileUtils;
import java.io.File;
public class SwaggerGenerator extends DefaultCodegen implements CodegenConfig {
private static final Logger LOGGER = LoggerFactory.getLogger(SwaggerGenerator.class);
public SwaggerGenerator() {
super();
embeddedTemplateDir = templateDir = "swagger";
@ -41,9 +47,9 @@ public class SwaggerGenerator extends DefaultCodegen implements CodegenConfig {
try {
String outputFile = outputFolder + File.separator + "swagger.json";
FileUtils.writeStringToFile(new File(outputFile), swaggerString);
System.out.println("wrote file to " + outputFile);
LOGGER.debug("wrote file to " + outputFile);
} catch (Exception e) {
e.printStackTrace();
LOGGER.error(e.getMessage(), e);
}
}
}

View File

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

View File

@ -37,10 +37,12 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
public static final String POD_DESCRIPTION = "podDescription";
public static final String POD_SCREENSHOTS = "podScreenshots";
public static final String POD_DOCUMENTATION_URL = "podDocumentationURL";
public static final String SWIFT_USE_API_NAMESPACE = "swiftUseApiNamespace";
protected static final String LIBRARY_PROMISE_KIT = "PromiseKit";
protected static final String[] RESPONSE_LIBRARIES = { LIBRARY_PROMISE_KIT };
protected String projectName = "SwaggerClient";
protected boolean unwrapRequired;
protected boolean swiftUseApiNamespace;
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_]+\\}");
@ -77,11 +79,13 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
"Bool",
"Void",
"String",
"Character")
"Character",
"AnyObject")
);
defaultIncludes = new HashSet<String>(
Arrays.asList(
"NSDate",
"NSURL", // for file
"Array",
"Dictionary",
"Set",
@ -89,7 +93,7 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
"Empty",
"AnyObject")
);
reservedWords = new HashSet<String>(
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",
@ -118,8 +122,11 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
typeMapping.put("float", "Float");
typeMapping.put("number", "Double");
typeMapping.put("double", "Double");
typeMapping.put("object", "String");
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>();
@ -139,6 +146,7 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
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
@ -173,6 +181,12 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
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"));
@ -181,11 +195,14 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
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"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
}
@Override
public String escapeReservedWord(String name) {
return "Swagger" + name; // add an underscore to the name
return "_" + name; // add an underscore to the name
}
@Override
@ -218,13 +235,64 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type))
return toModelName(type);
if (languageSpecificPrimitives.contains(type) || defaultIncludes.contains(type))
return type;
} else
type = swaggerType;
return toModelName(type);
}
/**
* Output the proper model name (capitalized)
*
* @param name the name of the model
* @return capitalized model name
*/
@Override
public String toModelName(String name) {
name = sanitizeName(name); // FIXME parameter should not be assigned. Also declare it as "final"
if (!StringUtils.isEmpty(modelNameSuffix)) { // set model suffix
name = name + "_" + modelNameSuffix;
}
if (!StringUtils.isEmpty(modelNamePrefix)) { // set model prefix
name = modelNamePrefix + "_" + name;
}
// 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;
}
// model name starts with number
if (name.matches("^\\d.*")) {
String modelName = "Model" + name; // e.g. 200Response => Model200Response (after camelize)
LOGGER.warn(name + " (model name starts with number) cannot be used as model name. Renamed to " + modelName);
return modelName;
}
return name;
}
/**
* 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
@ -260,13 +328,18 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
codegenProperty.allowableValues.put("values", swiftEnums);
codegenProperty.datatypeWithEnum =
StringUtils.left(codegenProperty.datatypeWithEnum, codegenProperty.datatypeWithEnum.length() - "Enum".length());
if (reservedWords.contains(codegenProperty.datatypeWithEnum)) {
// 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) {
// Prevent from breaking properly cased identifier
if (value.matches("[A-Z][a-z0-9]+[a-zA-Z0-9]*")) {
@ -284,9 +357,75 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
return initialCaps(name) + "API";
}
@Override
public String toOperationId(String operationId) {
operationId = camelize(sanitizeName(operationId), true);
// 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");
}
// method name cannot use reserved keyword, e.g. return
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;
}
return 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, 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);
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

View File

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

View File

@ -15,6 +15,16 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
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"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
//supportingFiles.add(new SupportingFile("gitignore.mustache", "", ".gitignore"));
}
public TypeScriptAngularClientCodegen() {
super();
outputFolder = "generated-code/typescript-angular";
@ -23,6 +33,5 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
embeddedTemplateDir = templateDir = "TypeScript-Angular";
apiPackage = "API.Client";
modelPackage = "API.Client";
supportingFiles.add(new SupportingFile("api.d.mustache", apiPackage().replace('.', File.separatorChar), "api.d.ts"));
}
}

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