Merge remote-tracking branch 'origin' into sync_master_230

This commit is contained in:
wing328 2017-02-10 23:31:36 +08:00
commit acd10318f7
1480 changed files with 60531 additions and 12438 deletions

View File

@ -1,3 +1,4 @@
.git/
*.iml
out/
*.ipr
@ -13,35 +14,13 @@ generated-sources/*
generated-code/*
*.swp
*.swo
/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/Build
samples/client/petstore/objc/Pods
samples/server/petstore/nodejs/node_modules
target
.idea
.lib
atlassian-ide-plugin.xml
*.bak
project/
samples/*
target/
.idea/
.lib/
.DS_Store
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/
# Not needed in a linux container
bin/windows/*

View File

@ -24,6 +24,12 @@ before_install:
- docker pull swaggerapi/petstore
- docker run -d -e SWAGGER_HOST=http://petstore.swagger.io -e SWAGGER_BASE_PATH=/v2 -p 80:8080 swaggerapi/petstore
- docker ps -a
# Add bats test framework and cURL for Bash script integration tests
- sudo add-apt-repository ppa:duggan/bats --yes
- sudo apt-get update -qq
- sudo apt-get install -qq bats
- sudo apt-get install -qq curl
# show host table to confirm petstore.swagger.io is mapped to localhost
- cat /etc/hosts
@ -34,7 +40,15 @@ install:
- export PATH="${TRAVIS_BUILD_DIR}/Godeps/_workspace/bin:$PATH"
script:
# fail fast
- set -e
# fail if templates/generators contain carriage return '\r'
- /bin/bash ./bin/utils/detect_carriage_return.sh
# fail if generators contain tab '\t'
- /bin/bash ./bin/utils/detect_tab_in_java_class.sh
# run integration tests defined in maven pom.xml
- mvn verify -Psamples
# docker test
- 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:

View File

@ -30,6 +30,7 @@ For a list of variables available in the template, please refer to this [page](h
### Style guide
Code change should conform to the programming style guide of the respective languages:
- Android: https://source.android.com/source/code-style.html
- Bash: https://github.com/bahamas10/bash-style-guide
- C#: https://msdn.microsoft.com/en-us/library/vstudio/ff926074.aspx
- C++: https://google.github.io/styleguide/cppguide.html
- Clojure: https://github.com/bbatsov/clojure-style-guide
@ -75,3 +76,5 @@ To start the CI tests, you can run `mvn verify -Psamples` (assuming you've all t
- Document the fix in the code to make the code more readable
- Make sure test cases passed after the change (one way is to leverage https://travis-ci.org/ to run the CI tests)
- File a PR with meaningful title, description and commit messages. A good example is [PR-3306](https://github.com/swagger-api/swagger-codegen/pull/3306)
- Recommended git settings
- `git config --global core.autocrlf input` to tell Git convert CRLF to LF on commit but not the other way around

View File

@ -1,13 +1,22 @@
FROM maven:3.3-jdk-7
FROM jimschubert/8-jdk-alpine-mvn:1.0
WORKDIR /src
VOLUME /src
VOLUME /root/.m2/repository
ENV GEN_DIR /opt/swagger-codegen
ADD . /opt/swagger-codegen
RUN set -x && \
apk add --no-cache bash
RUN cd /opt/swagger-codegen && mvn package
RUN mkdir /opt
ENTRYPOINT ["java", "-jar", "/opt/swagger-codegen/modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"]
ADD . ${GEN_DIR}
CMD ["help"]
VOLUME ${MAVEN_HOME}/.m2/repository
WORKDIR ${GEN_DIR}
RUN mvn -am -pl "modules/swagger-codegen-cli" package
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["build"]

111
README.md
View File

@ -15,8 +15,8 @@
## Overview
This is the swagger codegen project, which allows generation of API client libraries (SDK generation), server stubs and documentation automatically given an [OpenAPI Spec](https://github.com/OAI/OpenAPI-Specification). Currently, the following languages/frameworks are supported:
- **API clients**: **ActionScript**, **C#** (.net 2.0, 4.0 or later), **C++** (cpprest, Qt5, Tizen), **Clojure**, **Dart**, **Go**, **Groovy**, **Haskell**, **Java** (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign), **Node.js** (ES5, ES6, AngularJS with Google Closure Compiler annotations) **Objective-C**, **Perl**, **PHP**, **Python**, **Ruby**, **Scala**, **Swift** (2.x, 3.x), **Typescript** (Angular1.x, Angular2.x, Fetch, Node)
- **Server stubs**: **C#** (ASP.NET Core, NancyFx), **Erlang**, **Go**, **Haskell**, **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, RestEasy), **PHP** (Lumen, Slim, Silex), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Scala** (Scalatra)
- **API clients**: **ActionScript**, **Bash**, **C#** (.net 2.0, 4.0 or later), **C++** (cpprest, Qt5, Tizen), **Clojure**, **Dart**, **Elixir**, **Go**, **Groovy**, **Haskell**, **Java** (Jersey1.x, Jersey2.x, OkHttp, Retrofit1.x, Retrofit2.x, Feign), **Node.js** (ES5, ES6, AngularJS with Google Closure Compiler annotations) **Objective-C**, **Perl**, **PHP**, **Python**, **Ruby**, **Scala**, **Swift** (2.x, 3.x), **Typescript** (Angular1.x, Angular2.x, Fetch, Node)
- **Server stubs**: **C#** (ASP.NET Core, NancyFx), **Erlang**, **Go**, **Haskell**, **Java** (MSF4J, Spring, Undertow, JAX-RS: CDI, CXF, Inflector, RestEasy), **PHP** (Lumen, Slim, Silex, [Zend Expressive](https://github.com/zendframework/zend-expressive)), **Python** (Flask), **NodeJS**, **Ruby** (Sinatra, Rails5), **Scala** ([Finch](https://github.com/finagle/finch), Scalatra)
- **API documentation generators**: **HTML**, **Confluence Wiki**
- **Others**: **JMeter**
@ -110,16 +110,41 @@ After cloning the project, you can build it from source with this command:
mvn clean package
```
### Homebrew
To install, run `brew install swagger-codegen`
Here is an example usage:
```
swagger-codegen generate -i http://petstore.swagger.io/v2/swagger.json -l ruby -o /tmp/test/
```
### Docker
#### Build and run using docker
#### Development in docker
You can use `run-in-docker.sh` to do all development. This script maps your local repository to `/gen`
in the docker container. It also maps `~/.m2/repository` to the appropriate container location.
To execute `mvn package`:
```
git clone https://github.com/swagger-api/swagger-codegen
cd swagger-codegen
./run-in-docker.sh mvn package
```
```
Build artifacts are now accessible in your working directory.
Once built, `run-in-docker.sh` will act as an executable for swagger-codegen-cli. To generate code, you'll need to output to a directory under `/gen` (e.g. `/gen/out`). For example:
```
./run-in-docker.sh help # Executes 'help' command for swagger-codegen-cli
./run-in-docker.sh langs # Executes 'langs' command for swagger-codegen-cli
./run-in-docker.sh /gen/bin/go-petstore.sh # Builds the Go client
./run-in-docker.sh generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml \
-l go -o /gen/out/go-petstore -DpackageName=petstore # generates go client, outputs locally to ./out/go-petstore
```
#### Run Docker in Vagrant
Prerequisite: install [Vagrant](https://www.vagrantup.com/downloads.html) and [VirtualBox](https://www.virtualbox.org/wiki/Downloads).
@ -132,18 +157,54 @@ cd /vagrant
./run-in-docker.sh mvn package
```
#### Public Docker image
#### Public Pre-built Docker images
- https://hub.docker.com/r/swaggerapi/swagger-generator/ (official)
- https://hub.docker.com/r/jimschubert/swagger-codegen-cli/ (unofficial)
- https://hub.docker.com/r/swaggerapi/swagger-generator/ (official web service)
- https://hub.docker.com/r/swaggerapi/swagger-codegen-cli/ (official CLI)
=======
### Homebrew
To install, run `brew install swagger-codegen`
##### Swagger Generator Docker Image
The Swagger Generator image can act as a self-hosted web application and API for generating code. This container can be incorporated into a CI pipeline, and requires at least two HTTP requests and some docker orchestration to access generated code.
Example usage (note this assumes `jq` is installed for command line processing of JSON):
Here is an example usage:
```
swagger-codegen generate -i http://petstore.swagger.io/v2/swagger.json -l ruby -o /tmp/test/
# Start container and save the container id
CID=$(docker run -d swaggerapi/swagger-generator)
# allow for startup
sleep 5
# Get the IP of the running container
GEN_IP=$(docker inspect --format '{{.NetworkSettings.IPAddress}}' $CID)
# Execute an HTTP request and store the download link
RESULT=$(curl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{
"swaggerUrl": "http://petstore.swagger.io/v2/swagger.json"
}' 'http://localhost:8188/api/gen/clients/javascript' | jq '.link' | tr -d '"')
# Download the generated zip and redirect to a file
curl $RESULT > result.zip
# Shutdown the swagger generator image
docker stop $CID && docker rm $CID
```
In the example above, `result.zip` will contain the generated client.
##### Swagger Codegen Docker Image
The Swagger Codegen image acts as a standalone executable. It can be used as an alternative to installing via homebrew, or for developers who are unable to install Java or upgrade the installed version.
To generate code with this image, you'll need to mount a local location as a volume.
Example:
```
docker run --rm -v ${PWD}:/local swagger-api/swagger-codegen generate \
-i http://petstore.swagger.io/v2/swagger.json \
-l go \
-o /local/out/go
```
The generated code will be located under `./out/go` in the current directory.
## Getting Started
To generate a PHP client for http://petstore.swagger.io/v2/swagger.json, please run the following
@ -289,6 +350,10 @@ OPTIONS
the format of swaggerType=generatedType,swaggerType=generatedType.
For example: array=List,map=Map,string=String
--reserved-words-mappings <import mappings>
specifies how a reserved name should be escaped to. Otherwise, the
default _<name> is used. For example id=identifier
-v, --verbose
verbose mode
@ -331,6 +396,10 @@ You would then compile your library in the `output/myLibrary` folder with `mvn p
```
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
```
For Windows users, you will need to use `;` instead of `:` in the classpath, e.g.
```
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:
@ -459,6 +528,7 @@ AndroidClientCodegen.java
AspNet5ServerCodegen.java
AspNetCoreServerCodegen.java
AsyncScalaClientCodegen.java
BashClientCodegen.java
CSharpClientCodegen.java
ClojureClientCodegen.java
CsharpDotNet2ClientCodegen.java
@ -784,25 +854,32 @@ Here are some companies/projects using Swagger Codegen in production. To add you
- [goTransverse](http://www.gotransverse.com/api)
- [GraphHopper](https://graphhopper.com/)
- [Gravitate Solutions](http://gravitatesolutions.com/)
- [Hewlett Packard Enterprise](https://hpe.com)
- [High Technologies Center](http://htc-cs.com)
- [IMS Health](http://www.imshealth.com/en/solution-areas/technology-and-applications)
- [Intent HQ](http://www.intenthq.com)
- [Interactive Intelligence](http://developer.mypurecloud.com/)
- [Kabuku](http://www.kabuku.co.jp/en)
- [Kurio](https://kurio.co.id)
- [Kuroi](http://kuroiwebdesign.com/)
- [Kuary](https://kuary.com/)
- [Kubernetes](https://kubernetes.io/)
- [LANDR Audio](https://www.landr.com/)
- [Lascaux](http://www.lascaux.it/)
- [Leica Geosystems AG](http://leica-geosystems.com)
- [LiveAgent](https://www.ladesk.com/)
- [LXL Tech](http://lxltech.com)
- [MailMojo](https://mailmojo.no/)
- [Mindera](http://mindera.com/)
- [Mporium](http://mporium.com/)
- [Neverfail](https://neverfail.com/)
- [nViso](http://www.nviso.ch/)
- [Okiok](https://www.okiok.com)
- [Onedata](http://onedata.org)
- [OrderCloud.io](http://ordercloud.io)
- [OSDN](https://osdn.jp)
- [PagerDuty](https://www.pagerduty.com)
- [PagerTree](https://pagertree.com)
- [Pepipost](https://www.pepipost.com)
- [Plexxi](http://www.plexxi.com)
- [Pixoneye](http://www.pixoneye.com/)
@ -819,9 +896,12 @@ Here are some companies/projects using Swagger Codegen in production. To add you
- [Saritasa](https://www.saritasa.com/)
- [SCOOP Software GmbH](http://www.scoop-software.de)
- [Shine Solutions](https://shinesolutions.com/)
- [Simpfony](https://www.simpfony.com/)
- [Skurt](http://www.skurt.com)
- [Slamby](https://www.slamby.com/)
- [SmartRecruiters](https://www.smartrecruiters.com/)
- [snapCX](https://snapcx.io)
- [SPINEN](http://www.spinen.com)
- [SRC](https://www.src.si/)
- [StyleRecipe](http://stylerecipe.co.jp)
- [Svenska Spel AB](https://www.svenskaspel.se/)
@ -832,6 +912,7 @@ Here are some companies/projects using Swagger Codegen in production. To add you
- [VMware](https://vmware.com/)
- [W.UP](http://wup.hu/?siteLang=en)
- [Wealthfront](https://www.wealthfront.com/)
- [Webever GmbH](https://www.webever.de/)
- [WEXO A/S](https://www.wexo.dk/)
- [Zalando](https://tech.zalando.com)
- [ZEEF.com](https://zeef.com/)
@ -882,15 +963,19 @@ Swagger Codegen core team members are contributors who have been making signific
| Python Flask | |
| Ruby Sinatra | @wing328 (2016/05/01) | |
| Scala Scalatra | | |
| Scala Finch | @jimschubert (2017/01/28) |
## Template Creator
Here is a list of template creators:
* API Clients:
* Akka-Scala: @cchafer
* Bash: @bkryza
* C++ REST: @Danielku15
* C# (.NET 2.0): @who
* Clojure: @xhh
* Dart: @yissachar
* Elixir: @niku
* Groovy: @victorgit
* Go: @wing328
* Java (Feign): @davidkiss
@ -922,7 +1007,9 @@ Here is a list of template creators:
* JAX-RS CXF (CDI): @nickcmaynard
* PHP Lumen: @abcsum
* PHP Slim: @jfastnacht
* PHP Zend Expressive (with Path Handler): @Articus
* Ruby on Rails 5: @zlx
* Scala Finch: @jimschubert
* Documentation
* HTML Doc 2: @jhitchcock
* Confluence Wiki: @jhitchcock
@ -972,7 +1059,7 @@ When code is generated from this project, it shall be considered **AS IS** and o
License
-------
Copyright 2016 SmartBear Software
Copyright 2017 SmartBear Software
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

31
bin/bash-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"
args="$@ generate -t modules/swagger-codegen/src/main/resources/bash -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l bash -o samples/client/petstore/bash -c modules/swagger-codegen/src/test/resources/2_0/bash-config.json"
java $JAVA_OPTS -jar $executable $args

31
bin/elixir-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"
args="$@ generate -t modules/swagger-codegen/src/main/resources/elixir -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l elixir -o samples/client/petstore/elixir"
java $JAVA_OPTS -jar $executable $args

31
bin/finch-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/finch -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l finch -o samples/server/petstore/finch"
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/cxf -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l jaxrs-cxf -o samples/server/petstore/jaxrs-cxf-annotated-base-path -DhideGenerationTimestamp=true,useAnnotatedBasePath=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/cxf -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l jaxrs-cxf -o samples/server/petstore/jaxrs-cxf-non-spring-app -DhideGenerationTimestamp=true,generateNonSpringApplication=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/cxf -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l jaxrs-cxf -o samples/server/petstore/jaxrs-cxf -DhideGenerationTimestamp=true"
ags="$@ generate -t modules/swagger-codegen/src/main/resources/JavaJaxRS/cxf -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l jaxrs-cxf -o samples/server/petstore/jaxrs-cxf -DhideGenerationTimestamp=true"
java $JAVA_OPTS -jar $executable $ags

View File

@ -26,6 +26,7 @@ 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-spec -o samples/server/petstore/jaxrs-spec -DhideGenerationTimestamp=true"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l jaxrs-spec -o samples/server/petstore/jaxrs-spec
-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/nancyfx -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l nancyfx -o samples/server/petstore/nancyfx"
ags="generate $@ -t modules/swagger-codegen/src/main/resources/nancyfx -i modules/swagger-codegen/src/test/resources/2_0/petstore.yaml -l nancyfx -o samples/server/petstore/nancyfx"
java $JAVA_OPTS -jar $executable $ags

View File

@ -27,7 +27,7 @@ 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-with-fake-endpoints-models-for-testing.yaml -l perl -o samples/client/petstore/perl"
ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l perl -o samples/client/petstore/perl -DhideGenerationTimestamp=true"
java $JAVA_OPTS -jar $executable $ags

View File

@ -1,6 +1,8 @@
#!/bin/sh
./bin/spring-cloud-feign-petstore.sh
./bin/spring-delegate.sh
./bin/spring-delegate-j8.sh
./bin/spring-stubs.sh
./bin/spring-mvc-petstore-j8-async-server.sh
./bin/springboot-petstore-server.sh

34
bin/spring-delegate-j8.sh Executable file
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/JavaSpring -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l spring -o samples/server/petstore/springboot-delegate-j8 -DdelegatePattern=true,hideGenerationTimestamp=true,java8=true"
echo "Removing files and folders under samples/server/petstore/springboot-delegate-j8/src/main"
rm -rf samples/server/petstore/springboot-delegate-j8/src/main
find samples/server/petstore/springboot -maxdepth 1 -type f ! -name "README.md" -exec rm {} +
java $JAVA_OPTS -jar $executable $ags

34
bin/spring-delegate.sh Executable file
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/JavaSpring -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l spring -o samples/server/petstore/springboot-delegate -DdelegatePattern=true,hideGenerationTimestamp=true"
echo "Removing files and folders under samples/server/petstore/springboot-delegate/src/main"
rm -rf samples/server/petstore/springboot-delegate/src/main
find samples/server/petstore/springboot -maxdepth 1 -type f ! -name "README.md" -exec rm {} +
java $JAVA_OPTS -jar $executable $ags

View File

@ -0,0 +1,18 @@
#!/bin/bash
# grep for \r in the templates
grep -RUIl $'\r$' modules/swagger-codegen/src/main/resources/*
if [ $? -ne 1 ]; then
echo "Templates contain carriage return '/r'. Please remove it and try again."
exit 1;
fi
# grep for \r in the generators
grep -RUIl $'\r$' modules/swagger-codegen/src/main/java/io/swagger/codegen/*.java
if [ $? -ne 1 ]; then
echo "Generators contain carriage return '/r'. Please remove it and try again."
exit 1;
fi

View File

@ -0,0 +1,10 @@
#!/bin/bash
# grep for \t in the generators
grep -RUIl $'\t$' modules/swagger-codegen/src/main/java/io/swagger/codegen/*.java
if [ $? -ne 1 ]; then
echo "Generators (Java class files) contain tab '/t'. Please remove it and try again."
exit 1;
fi

View File

@ -0,0 +1,2 @@
call .\bin\windows\javascript-petstore.bat
call .\bin\windows\javascript-promise-petstore.bat

View File

@ -5,6 +5,6 @@ If Not Exist %executable% (
)
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
set ags=generate -i modules\swagger-codegen\src\test\resources\2_0\petstore.json -l javascript -o samples\client\petstore\javascript
set ags=generate -i modules\swagger-codegen\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -l javascript -o samples\client\petstore\javascript
java %JAVA_OPTS% -jar %executable% %ags%
java -DappName=PetstoreClient %JAVA_OPTS% -jar %executable% %ags%

View File

@ -0,0 +1,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
set ags=generate -i modules\swagger-codegen\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -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,10 @@
set executable=.\modules\swagger-codegen-cli\target\swagger-codegen-cli.jar
If Not Exist %executable% (
mvn clean package
)
REM set JAVA_OPTS=%JAVA_OPTS% -Xmx1024M
set ags=generate -i modules\swagger-codegen\src\test\resources\2_0\petstore-with-fake-endpoints-models-for-testing.yaml -l ze-ph -o samples\server\petstore\ze-ph
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/ze-ph -i modules/swagger-codegen/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -l ze-ph -o samples/server/petstore/ze-ph"
java $JAVA_OPTS -jar $executable $ags

24
docker-entrypoint.sh Executable file
View File

@ -0,0 +1,24 @@
#!/usr/bin/env bash
set -euo pipefail
# GEN_DIR allows to share the entrypoint between Dockerfile and run-in-docker.sh (backward compatible)
GEN_DIR=${GEN_DIR:-/opt/swagger-codegen}
JAVA_OPTS=${JAVA_OPTS:-"-Xmx1024M -DloggerPath=conf/log4j.properties"}
codegen="${GEN_DIR}/modules/swagger-codegen-cli/target/swagger-codegen-cli.jar"
case "$1" in
generate|help|langs|meta|config-help)
# If ${GEN_DIR} has been mapped elsewhere from default, and that location has not been built
if [[ ! -f "${codegen}" ]]; then
(cd ${GEN_DIR} && exec mvn -am -pl "modules/swagger-codegen-cli" package)
fi
command=$1
shift
exec java ${JAVA_OPTS} -jar ${codegen} ${command} "$@"
;;
*) # Any other commands, e.g. docker run imagename ls -la or docker run -it imagename /bin/bash
exec "$@"
;;
esac

View File

@ -0,0 +1,7 @@
FROM java:8-jre-alpine
ADD target/swagger-codegen-cli.jar /opt/swagger-codegen-cli/swagger-codegen-cli.jar
ENTRYPOINT ["java", "-jar", "/opt/swagger-codegen-cli/swagger-codegen-cli.jar"]
CMD ["help"]

View File

@ -117,7 +117,14 @@ public class Generate implements Runnable {
@Option(name = {"--http-user-agent"}, title = "http user agent", description = CodegenConstants.HTTP_USER_AGENT_DESC)
private String httpUserAgent;
@Option(name = {"--reserved-words-mappings"}, title = "import mappings",
description = "specifies how a reserved name should be escaped to. Otherwise, the default _<name> is used. For example id=identifier")
private String reservedWordsMappings;
@Option(name = {"--ignore-file-override"}, title = "ignore file override location", description = CodegenConstants.IGNORE_FILE_OVERRIDE_DESC)
private String ignoreFileOverride;
@Override
public void run() {
@ -211,13 +218,17 @@ public class Generate implements Runnable {
configurator.setHttpUserAgent(httpUserAgent);
}
if (isNotEmpty(ignoreFileOverride)) {
configurator.setIgnoreFileOverride(ignoreFileOverride);
}
applySystemPropertiesKvp(systemProperties, configurator);
applyInstantiationTypesKvp(instantiationTypes, configurator);
applyImportMappingsKvp(importMappings, configurator);
applyTypeMappingsKvp(typeMappings, configurator);
applyAdditionalPropertiesKvp(additionalProperties, configurator);
applyLanguageSpecificPrimitivesCsv(languageSpecificPrimitives, configurator);
applyReservedWordsMappingsKvp(reservedWordsMappings, configurator);
final ClientOptInput clientOptInput = configurator.toClientOptInput();
new DefaultGenerator().opts(clientOptInput).generate();

View File

@ -45,9 +45,11 @@ mvn clean compile
- `modelPackage` - the package to use for generated model objects/classes
- `apiPackage` - the package to use for generated api objects/classes
- `invokerPackage` - the package to use for the generated invoker objects
- `modelNamePrefix` and `modelNameSuffix` - Sets the pre- or suffix for model classes and enums.
- `modelNamePrefix` and `modelNameSuffix` - Sets the pre- or suffix for model classes and enums
- `useJaxbAnnotations` - enable Jaxb annotations inside the generated models
- `configOptions` - a map of language-specific parameters (see below)
- `configHelp` - dumps the configuration help for the specified library (generates no sources)
- `ignoreFileOverride` - specifies the full path to a `.swagger-codegen-ignore` used for pattern based overrides of generated outputs
### Custom Generator

View File

@ -21,6 +21,7 @@ import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyImportMapp
import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyInstantiationTypesKvp;
import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyLanguageSpecificPrimitivesCsv;
import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyTypeMappingsKvp;
import static io.swagger.codegen.config.CodegenConfiguratorUtils.applyReservedWordsMappingsKvp;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
import java.io.File;
@ -161,6 +162,12 @@ public class CodeGenMojo extends AbstractMojo {
@Parameter(name = "modelNameSuffix", required = false)
private String modelNameSuffix;
/**
* Sets an optional ignoreFileOverride path
*/
@Parameter(name = "ignoreFileOverride", required = false)
private String ignoreFileOverride;
/**
* A map of language-specific parameters as passed with the -c option to the command line
*/
@ -215,6 +222,10 @@ public class CodeGenMojo extends AbstractMojo {
configurator.setGitRepoId(gitRepoId);
}
if(isNotEmpty(ignoreFileOverride)) {
configurator.setIgnoreFileOverride(ignoreFileOverride);
}
configurator.setLang(language);
configurator.setOutputDir(output.getAbsolutePath());
@ -284,6 +295,10 @@ public class CodeGenMojo extends AbstractMojo {
if(configOptions.containsKey("additional-properties")) {
applyAdditionalPropertiesKvp(configOptions.get("additional-properties").toString(), configurator);
}
if(configOptions.containsKey("reserved-words-mappings")) {
applyReservedWordsMappingsKvp(configOptions.get("reserved-words-mappings").toString(), configurator);
}
}
if (environmentVariables != null) {
@ -330,7 +345,7 @@ public class CodeGenMojo extends AbstractMojo {
}
if (addCompileSourceRoot) {
final Object sourceFolderObject = configOptions.get(CodegenConstants.SOURCE_FOLDER);
final Object sourceFolderObject = configOptions == null ? null : configOptions.get(CodegenConstants.SOURCE_FOLDER);
final String sourceFolder = sourceFolderObject == null ? "src/main/java" : sourceFolderObject.toString();
String sourceJavaFolder = output.toString() + "/" + sourceFolder;

View File

@ -56,7 +56,7 @@ public abstract class AbstractGenerator {
if (is == null) {
is = new FileInputStream(new File(name)); // May throw but never return a null value
}
return new InputStreamReader(is);
return new InputStreamReader(is, "UTF-8");
} catch (Exception e) {
LOGGER.error(e.getMessage());
}

View File

@ -25,9 +25,9 @@ import io.swagger.parser.SwaggerParser;
*/
@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:" +

View File

@ -14,7 +14,7 @@ import com.samskivert.mustache.Mustache.Compiler;
public interface CodegenConfig {
CodegenType getTag();
String getName();
String getHelp();
@ -118,6 +118,8 @@ public interface CodegenConfig {
Map<String, String> modelDocTemplateFiles();
Set<String> languageSpecificPrimitives();
Map<String, String> reservedWordsMappings();
void preprocessSwagger(Swagger swagger);
@ -197,4 +199,8 @@ public interface CodegenConfig {
String getHttpUserAgent();
String getCommonTemplateDir();
void setIgnoreFilePathOverride(String ignoreFileOverride);
String getIgnoreFilePathOverride();
}

View File

@ -12,6 +12,8 @@ public class CodegenConstants {
public static final String TEMPLATE_DIR = "templateDir";
public static final String ALLOW_UNICODE_IDENTIFIERS = "allowUnicodeIdentifiers";
public static final String ALLOW_UNICODE_IDENTIFIERS_DESC = "boolean, toggles whether unicode identifiers are allowed in names or not, default is false";
public static final String INVOKER_PACKAGE = "invokerPackage";
public static final String INVOKER_PACKAGE_DESC = "root package for generated code";
@ -19,6 +21,12 @@ public class CodegenConstants {
public static final String PHP_INVOKER_PACKAGE = "phpInvokerPackage";
public static final String PHP_INVOKER_PACKAGE_DESC = "root package for generated php code";
public static final String PERL_MODULE_NAME = "perlModuleName";
public static final String PERL_MODULE_NAME_DESC = "root module name for generated perl code";
public static final String PYTHON_PACKAGE_NAME = "pythonPackageName";
public static final String PYTHON_PACKAGE_NAME_DESC = "package name for generated python code";
public static final String GROUP_ID = "groupId";
public static final String GROUP_ID_DESC = "groupId in generated pom.xml";
@ -28,6 +36,33 @@ public class CodegenConstants {
public static final String ARTIFACT_VERSION = "artifactVersion";
public static final String ARTIFACT_VERSION_DESC = "artifact version in generated pom.xml";
public static final String ARTIFACT_URL = "artifactUrl";
public static final String ARTIFACT_URL_DESC = "artifact URL in generated pom.xml";
public static final String ARTIFACT_DESCRIPTION = "artifactDescription";
public static final String ARTIFACT_DESCRIPTION_DESC = "artifact description in generated pom.xml";
public static final String SCM_CONNECTION = "scmConnection";
public static final String SCM_CONNECTION_DESC = "SCM connection in generated pom.xml";
public static final String SCM_DEVELOPER_CONNECTION = "scmDeveloperConnection";
public static final String SCM_DEVELOPER_CONNECTION_DESC = "SCM developer connection in generated pom.xml";
public static final String SCM_URL = "scmUrl";
public static final String SCM_URL_DESC = "SCM URL in generated pom.xml";
public static final String DEVELOPER_NAME = "developerName";
public static final String DEVELOPER_NAME_DESC = "developer name in generated pom.xml";
public static final String DEVELOPER_EMAIL = "developerEmail";
public static final String DEVELOPER_EMAIL_DESC = "developer email in generated pom.xml";
public static final String DEVELOPER_ORGANIZATION = "developerOrganization";
public static final String DEVELOPER_ORGANIZATION_DESC = "developer organization in generated pom.xml";
public static final String DEVELOPER_ORGANIZATION_URL = "developerOrganizationUrl";
public static final String DEVELOPER_ORGANIZATION_URL_DESC = "developer organization URL in generated pom.xml";
public static final String LICENSE_NAME = "licenseName";
public static final String LICENSE_NAME_DESC = "The name of the license";
@ -86,6 +121,9 @@ public class CodegenConstants {
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 INTERFACE_PREFIX = "interfacePrefix";
public static final String INTERFACE_PREFIX_DESC = "Prefix interfaces with a community standard or widely accepted prefix.";
public static final String RETURN_ICOLLECTION = "returnICollection";
public static final String RETURN_ICOLLECTION_DESC = "Return ICollection<T> instead of the concrete type.";
@ -137,8 +175,15 @@ public class CodegenConstants {
public static final String GENERATE_MODEL_TESTS_DESC = "Specifies that model tests are to be generated.";
public static final String HIDE_GENERATION_TIMESTAMP = "hideGenerationTimestamp";
public static final String HIDE_GENERATION_TIMESTAMP_DESC = "Hides the generation timestamp.";
public static final String HIDE_GENERATION_TIMESTAMP_DESC = "Hides the generation timestamp when files are generated.";
public static final String GENERATE_PROPERTY_CHANGED = "generatePropertyChanged";
public static final String GENERATE_PROPERTY_CHANGED_DESC = "Specifies that models support raising property changed events.";
public static final String NON_PUBLIC_API = "nonPublicApi";
public static final String NON_PUBLIC_API_DESC = "Generates code with reduced access modifiers; allows embedding elsewhere without exposing non-public API calls to consumers.";
public static final String IGNORE_FILE_OVERRIDE = "ignoreFileOverride";
public static final String IGNORE_FILE_OVERRIDE_DESC = "Specifies an override location for the .swagger-codegen-ignore file. Most useful on initial generation.";
}

View File

@ -90,6 +90,7 @@ public class CodegenParameter {
output.collectionFormat = this.collectionFormat;
output.isCollectionFormatMulti = this.isCollectionFormatMulti;
output.description = this.description;
output.unescapedDescription = this.unescapedDescription;
output.baseType = this.baseType;
output.isFormParam = this.isFormParam;
output.isQueryParam = this.isQueryParam;

View File

@ -7,9 +7,11 @@ import java.util.Map;
import java.util.Objects;
public class CodegenProperty implements Cloneable {
public String baseName, complexType, getter, setter, description, datatype, datatypeWithEnum,
dataFormat, name, min, max, defaultValue, defaultValueWithParam, baseType, containerType;
public String baseName, complexType, getter, setter, description, datatype,
datatypeWithEnum, dataFormat, name, min, max, defaultValue, defaultValueWithParam,
baseType, containerType, title;
/** The 'description' string without escape charcters needed by some programming languages/targets */
public String unescapedDescription;
/**
@ -49,7 +51,10 @@ public class CodegenProperty implements Cloneable {
public boolean isInherited;
public String nameInCamelCase; // property name in camel case
// enum name based on the property name, usually use as a prefix (e.g. VAR_NAME) for enum name (e.g. VAR_NAME_VALUE1)
public String enumName;
public String enumName;
public Integer maxItems;
public Integer minItems;
@Override
public String toString() {
@ -74,6 +79,7 @@ public class CodegenProperty implements Cloneable {
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 + ((title == null) ? 0 : title.hashCode());
result = prime * result + ((example == null) ? 0 : example.hashCode());
result = prime * result + (exclusiveMaximum ? 13:31);
result = prime * result + (exclusiveMinimum ? 13:31);
@ -117,6 +123,8 @@ public class CodegenProperty implements Cloneable {
result = prime * result + Objects.hashCode(isInherited);
result = prime * result + Objects.hashCode(nameInCamelCase);
result = prime * result + Objects.hashCode(enumName);
result = prime * result + ((maxItems == null) ? 0 : maxItems.hashCode());
result = prime * result + ((minItems == null) ? 0 : minItems.hashCode());
return result;
}
@ -144,6 +152,9 @@ public class CodegenProperty implements Cloneable {
if ((this.description == null) ? (other.description != null) : !this.description.equals(other.description)) {
return false;
}
if ((this.title == null) ? (other.title != null) : !this.title.equals(other.title)) {
return false;
}
if ((this.datatype == null) ? (other.datatype != null) : !this.datatype.equals(other.datatype)) {
return false;
}
@ -283,6 +294,12 @@ public class CodegenProperty implements Cloneable {
if (!Objects.equals(this.enumName, other.enumName)) {
return false;
}
if (this.maxItems != other.maxItems && (this.maxItems == null || !this.maxItems.equals(other.maxItems))) {
return false;
}
if (this.minItems != other.minItems && (this.minItems == null || !this.minItems.equals(other.minItems))) {
return false;
}
return true;
}
@ -307,6 +324,6 @@ public class CodegenProperty implements Cloneable {
throw new IllegalStateException(e);
}
}
}

View File

@ -19,6 +19,7 @@ public class CodegenResponse {
public Boolean isFile = Boolean.FALSE;
public Object schema;
public String jsonSchema;
public Map<String, Object> vendorExtensions;
public boolean isWildcard() {
return "0".equals(code) || "default".equals(code);
@ -68,6 +69,8 @@ public class CodegenResponse {
return false;
if (schema != null ? !schema.equals(that.schema) : that.schema != null)
return false;
if (vendorExtensions != null ? !vendorExtensions.equals(that.vendorExtensions) : that.vendorExtensions != null)
return false;
return jsonSchema != null ? jsonSchema.equals(that.jsonSchema) : that.jsonSchema == null;
}
@ -91,6 +94,7 @@ public class CodegenResponse {
result = 31 * result + (isFile != null ? isFile.hashCode() : 0);
result = 31 * result + (schema != null ? schema.hashCode() : 0);
result = 31 * result + (jsonSchema != null ? jsonSchema.hashCode() : 0);
result = 31 * result + (vendorExtensions != null ? vendorExtensions.hashCode() : 0);
return result;
}
}

View File

@ -92,6 +92,7 @@ public class DefaultCodegen {
protected Map<String, String> modelTestTemplateFiles = new HashMap<String, String>();
protected Map<String, String> apiDocTemplateFiles = new HashMap<String, String>();
protected Map<String, String> modelDocTemplateFiles = new HashMap<String, String>();
protected Map<String, String> reservedWordsMappings = new HashMap<String, String>();
protected String templateDir;
protected String embeddedTemplateDir;
protected String commonTemplateDir = "_common";
@ -106,6 +107,7 @@ public class DefaultCodegen {
protected String library;
protected Boolean sortParamsByRequiredFlag = true;
protected Boolean ensureUniqueParams = true;
protected Boolean allowUnicodeIdentifiers = false;
protected String gitUserId, gitRepoId, releaseNote;
protected String httpUserAgent;
protected Boolean hideGenerationTimestamp = true;
@ -114,6 +116,8 @@ public class DefaultCodegen {
// Then translated back during JSON encoding and decoding
protected Map<String, String> specialCharReplacements = new HashMap<String, String>();
protected String ignoreFilePathOverride;
public List<CliOption> cliOptions() {
return cliOptions;
}
@ -141,6 +145,11 @@ public class DefaultCodegen {
.get(CodegenConstants.ENSURE_UNIQUE_PARAMS).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS)) {
this.setAllowUnicodeIdentifiers(Boolean.valueOf(additionalProperties
.get(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS).toString()));
}
if(additionalProperties.containsKey(CodegenConstants.MODEL_NAME_PREFIX)){
this.setModelNamePrefix((String) additionalProperties.get(CodegenConstants.MODEL_NAME_PREFIX));
}
@ -148,7 +157,6 @@ public class DefaultCodegen {
if(additionalProperties.containsKey(CodegenConstants.MODEL_NAME_SUFFIX)){
this.setModelNameSuffix((String) additionalProperties.get(CodegenConstants.MODEL_NAME_SUFFIX));
}
}
// override with any special post-processing for all models
@ -185,12 +193,18 @@ public class DefaultCodegen {
for (String name : allModels.keySet()) {
CodegenModel cm = allModels.get(name);
CodegenModel parent = allModels.get(cm.parent);
// if a discriminator exists on the parent, don't add this child to the inheritance heirarchy
// TODO Determine what to do if the parent discriminator name == the grandparent discriminator name
while (parent != null) {
if (parent.children == null) {
parent.children = new ArrayList<CodegenModel>();
parent.children = new ArrayList<CodegenModel>();
}
parent.children.add(cm);
parent = allModels.get(parent.parent);
if (parent.discriminator == null) {
parent = allModels.get(parent.parent);
} else {
parent = null;
}
}
}
}
@ -303,6 +317,10 @@ public class DefaultCodegen {
* @return the sanitized variable name for enum
*/
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
return "EMPTY";
}
String var = value.replaceAll("\\W+", "_").toUpperCase();
if (var.matches("\\d.*")) {
return "_" + var;
@ -346,7 +364,7 @@ public class DefaultCodegen {
// override with any special handling of the JMustache compiler
@SuppressWarnings("unused")
public Compiler processCompiler(Compiler compiler) {
return compiler;
return compiler;
}
// override with any special text escaping logic
@ -464,6 +482,10 @@ public class DefaultCodegen {
public Map<String, String> modelDocTemplateFiles() {
return modelDocTemplateFiles;
}
public Map<String, String> reservedWordsMappings() {
return reservedWordsMappings;
}
public Map<String, String> apiTestTemplateFiles() {
return apiTestTemplateFiles;
@ -565,6 +587,10 @@ public class DefaultCodegen {
this.ensureUniqueParams = ensureUniqueParams;
}
public void setAllowUnicodeIdentifiers(Boolean allowUnicodeIdentifiers) {
this.allowUnicodeIdentifiers = allowUnicodeIdentifiers;
}
/**
* Return the regular expression/JSON schema pattern (http://json-schema.org/latest/json-schema-validation.html#anchor33)
*
@ -819,6 +845,10 @@ public class DefaultCodegen {
cliOptions.add(CliOption.newBoolean(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants
.ENSURE_UNIQUE_PARAMS_DESC).defaultValue(Boolean.TRUE.toString()));
//name formatting options
cliOptions.add(CliOption.newBoolean(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS, CodegenConstants
.ALLOW_UNICODE_IDENTIFIERS_DESC).defaultValue(Boolean.FALSE.toString()));
// initialize special character mapping
initalizeSpecialCharacterMapping();
}
@ -1261,6 +1291,18 @@ public class DefaultCodegen {
allProperties = new LinkedHashMap<String, Property>();
allRequired = new ArrayList<String>();
m.allVars = new ArrayList<CodegenProperty>();
int modelImplCnt = 0; // only one inline object allowed in a ComposedModel
for (Model innerModel: ((ComposedModel)model).getAllOf()) {
if (innerModel instanceof ModelImpl) {
if (m.discriminator == null) {
m.discriminator = ((ModelImpl) innerModel).getDiscriminator();
}
if (modelImplCnt++ > 1) {
LOGGER.warn("More than one inline schema specified in allOf:. Only the first one is recognized. All others are ignored.");
break; // only one ModelImpl with discriminator allowed in allOf
}
}
}
} else {
allProperties = null;
allRequired = null;
@ -1436,6 +1478,7 @@ public class DefaultCodegen {
property.nameInCamelCase = camelize(property.name, false);
property.description = escapeText(p.getDescription());
property.unescapedDescription = p.getDescription();
property.title = p.getTitle();
property.getter = "get" + getterAndSetterCapitalize(name);
property.setter = "set" + getterAndSetterCapitalize(name);
property.example = toExampleValue(p);
@ -1680,16 +1723,18 @@ public class DefaultCodegen {
property.baseType = getSwaggerType(p);
if (p instanceof ArrayProperty) {
if (p instanceof ArrayProperty) {
property.isContainer = true;
property.isListContainer = true;
property.containerType = "array";
property.baseType = getSwaggerType(p);
// handle inner property
ArrayProperty ap = (ArrayProperty) p;
property.maxItems = ap.getMaxItems();
property.minItems = ap.getMinItems();
CodegenProperty cp = fromProperty(property.name, ap.getItems());
updatePropertyForArray(property, cp);
} else if (p instanceof MapProperty) {
} else if (p instanceof MapProperty) {
property.isContainer = true;
property.isMapContainer = true;
property.containerType = "map";
@ -1714,6 +1759,7 @@ public class DefaultCodegen {
LOGGER.warn("skipping invalid array property " + Json.pretty(property));
return;
}
property.dataFormat = innerProperty.dataFormat;
if (!languageSpecificPrimitives.contains(innerProperty.baseType)) {
property.complexType = innerProperty.baseType;
} else {
@ -1750,6 +1796,7 @@ public class DefaultCodegen {
property.isPrimitiveType = true;
}
property.items = innerProperty;
property.dataFormat = innerProperty.dataFormat;
// inner item is Enum
if (isPropertyInnerMostEnum(property)) {
// isEnum is set to true when the type is an enum
@ -1876,7 +1923,7 @@ public class DefaultCodegen {
* @return Codegen Operation object
*/
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions) {
return fromOperation(path, httpMethod, operation, definitions, null);
return fromOperation(path, httpMethod, operation, definitions, null);
}
/**
@ -2184,6 +2231,7 @@ public class DefaultCodegen {
r.schema = response.getSchema();
r.examples = toExamples(response.getExamples());
r.jsonSchema = Json.pretty(response);
r.vendorExtensions = response.getVendorExtensions();
addHeaders(response, r.headers);
if (r.schema != null) {
@ -2354,7 +2402,7 @@ public class DefaultCodegen {
// validation
// handle maximum, minimum properly for int/long by removing the trailing ".0"
if ("integer".equals(type)) {
if ("integer".equals(qp.getType())) {
p.maximum = qp.getMaximum() == null ? null : String.valueOf(qp.getMaximum().longValue());
p.minimum = qp.getMinimum() == null ? null : String.valueOf(qp.getMinimum().longValue());
} else {
@ -2531,7 +2579,7 @@ public class DefaultCodegen {
@SuppressWarnings("static-method")
public List<CodegenSecurity> fromSecurity(Map<String, SecuritySchemeDefinition> schemes) {
if (schemes == null) {
return Collections.emptyList();
return Collections.emptyList();
}
List<CodegenSecurity> secs = new ArrayList<CodegenSecurity>(schemes.size());
@ -2555,8 +2603,8 @@ public class DefaultCodegen {
sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = sec.isOAuth = false;
sec.isBasic = true;
} else {
final OAuth2Definition oauth2Definition = (OAuth2Definition) schemeDefinition;
sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = sec.isBasic = false;
final OAuth2Definition oauth2Definition = (OAuth2Definition) schemeDefinition;
sec.isKeyInHeader = sec.isKeyInQuery = sec.isApiKey = sec.isBasic = false;
sec.isOAuth = true;
sec.flow = oauth2Definition.getFlow();
if (sec.flow == null) {
@ -3191,11 +3239,11 @@ public class DefaultCodegen {
// encountered so far and hopefully make it easier for others to add more special
// cases in the future.
// better error handling when map/array type is invalid
if (name == null) {
LOGGER.error("String to be sanitized is null. Default to ERROR_UNKNOWN");
return "ERROR_UNKNOWN";
}
// better error handling when map/array type is invalid
if (name == null) {
LOGGER.error("String to be sanitized is null. Default to ERROR_UNKNOWN");
return "ERROR_UNKNOWN";
}
// if the name is just '$', map it to 'value' for the time being.
if ("$".equals(name)) {
@ -3224,7 +3272,14 @@ public class DefaultCodegen {
// remove everything else other than word, number and _
// $php_variable => php_variable
return name.replaceAll("[^a-zA-Z0-9_]", "");
if (allowUnicodeIdentifiers) { //could be converted to a single line with ?: operator
name = Pattern.compile("\\W", Pattern.UNICODE_CHARACTER_CLASS).matcher(name).replaceAll("");
}
else {
name = name.replaceAll("\\W", "");
}
return name;
}
/**
@ -3416,11 +3471,44 @@ public class DefaultCodegen {
public boolean convertPropertyToBooleanAndWriteBack(String propertyKey) {
boolean booleanValue = false;
if (additionalProperties.containsKey(propertyKey)) {
booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString());
booleanValue = convertPropertyToBoolean(propertyKey);
// write back as boolean
additionalProperties.put(propertyKey, booleanValue);
writePropertyBack(propertyKey, booleanValue);
}
return booleanValue;
}
/**
* Provides an override location, if any is specified, for the .swagger-codegen-ignore.
*
* This is originally intended for the first generation only.
*
* @return a string of the full path to an override ignore file.
*/
public String getIgnoreFilePathOverride() {
return ignoreFilePathOverride;
}
/**
* Sets an override location for the .swagger-codegen.ignore location for the first code generation.
*
* @param ignoreFileOverride The full path to an ignore file
*/
public void setIgnoreFilePathOverride(final String ignoreFileOverride) {
this.ignoreFilePathOverride = ignoreFileOverride;
}
public boolean convertPropertyToBoolean(String propertyKey) {
boolean booleanValue = false;
if (additionalProperties.containsKey(propertyKey)) {
booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString());
}
return booleanValue;
}
public void writePropertyBack(String propertyKey, boolean value) {
additionalProperties.put(propertyKey, value);
}
}

View File

@ -42,7 +42,21 @@ public class DefaultGenerator extends AbstractGenerator implements Generator {
this.swagger = opts.getSwagger();
this.config = opts.getConfig();
this.config.additionalProperties().putAll(opts.getOpts().getProperties());
ignoreProcessor = new CodegenIgnoreProcessor(this.config.getOutputDir());
String ignoreFileLocation = this.config.getIgnoreFilePathOverride();
if(ignoreFileLocation != null) {
final File ignoreFile = new File(ignoreFileLocation);
if(ignoreFile.exists() && ignoreFile.canRead()) {
this.ignoreProcessor = new CodegenIgnoreProcessor(ignoreFile);
} else {
LOGGER.warn("Ignore file specified at {} is not valid. This will fall back to an existing ignore file if present in the output directory.", ignoreFileLocation);
}
}
if(this.ignoreProcessor == null) {
this.ignoreProcessor = new CodegenIgnoreProcessor(this.config.getOutputDir());
}
return this;
}

View File

@ -54,12 +54,15 @@ public class CodegenConfigurator {
private String artifactId;
private String artifactVersion;
private String library;
private String ignoreFileOverride;
private Map<String, String> systemProperties = new HashMap<String, String>();
private Map<String, String> instantiationTypes = new HashMap<String, String>();
private Map<String, String> typeMappings = new HashMap<String, String>();
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
private Map<String, String> importMappings = new HashMap<String, String>();
private Set<String> languageSpecificPrimitives = new HashSet<String>();
private Map<String, String> reservedWordMappings = new HashMap<String, String>();
private String gitUserId="GIT_USER_ID";
private String gitRepoId="GIT_REPO_ID";
private String releaseNote="Minor update";
@ -263,7 +266,7 @@ public class CodegenConfigurator {
this.additionalProperties = additionalProperties;
return this;
}
public CodegenConfigurator addAdditionalProperty(String key, Object value) {
this.additionalProperties.put(key, value);
return this;
@ -341,7 +344,30 @@ public class CodegenConfigurator {
this.httpUserAgent= httpUserAgent;
return this;
}
public Map<String, String> getReservedWordsMappings() {
return reservedWordMappings;
}
public CodegenConfigurator setReservedWordsMappings(Map<String, String> reservedWordsMappings) {
this.reservedWordMappings = reservedWordsMappings;
return this;
}
public CodegenConfigurator addAdditionalReservedWordMapping(String key, String value) {
this.reservedWordMappings.put(key, value);
return this;
}
public String getIgnoreFileOverride() {
return ignoreFileOverride;
}
public CodegenConfigurator setIgnoreFileOverride(final String ignoreFileOverride) {
this.ignoreFileOverride = ignoreFileOverride;
return this;
}
public ClientOptInput toClientOptInput() {
Validate.notEmpty(lang, "language must be specified");
@ -355,12 +381,14 @@ public class CodegenConfigurator {
config.setInputSpec(inputSpec);
config.setOutputDir(outputDir);
config.setSkipOverwrite(skipOverwrite);
config.setIgnoreFilePathOverride(ignoreFileOverride);
config.instantiationTypes().putAll(instantiationTypes);
config.typeMapping().putAll(typeMappings);
config.importMapping().putAll(importMappings);
config.languageSpecificPrimitives().addAll(languageSpecificPrimitives);
config.reservedWordsMappings().putAll(reservedWordMappings);
checkAndSetAdditionalProperty(apiPackage, CodegenConstants.API_PACKAGE);
checkAndSetAdditionalProperty(modelPackage, CodegenConstants.MODEL_PACKAGE);
checkAndSetAdditionalProperty(invokerPackage, CodegenConstants.INVOKER_PACKAGE);

View File

@ -58,6 +58,13 @@ public final class CodegenConfiguratorUtils {
}
}
public static void applyReservedWordsMappingsKvp(String reservedWordMappings, CodegenConfigurator configurator) {
final Map<String, String> map = createMapFromKeyValuePairs(reservedWordMappings);
for (Map.Entry<String, String> entry : map.entrySet()) {
configurator.addAdditionalReservedWordMapping(entry.getKey(), entry.getValue());
}
}
private static Set<String> createSetFromCsvList(String csvProperty) {
final List<String> values = OptionUtils.splitCommaSeparatedList(csvProperty);
return new HashSet<String>(values);
@ -74,4 +81,6 @@ public final class CodegenConfiguratorUtils {
return result;
}
}

View File

@ -9,13 +9,22 @@ 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.IntegerProperty;
import io.swagger.models.properties.LongProperty;
import io.swagger.models.properties.DecimalProperty;
import io.swagger.models.properties.DoubleProperty;
import io.swagger.models.properties.BaseIntegerProperty;
import io.swagger.models.properties.AbstractNumericProperty;
import io.swagger.models.properties.PasswordProperty;
import io.swagger.models.properties.UUIDProperty;
import io.swagger.models.properties.Property;
import io.swagger.models.properties.RefProperty;
import io.swagger.models.properties.StringProperty;
import org.codehaus.plexus.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@ -25,6 +34,7 @@ import java.util.Map;
import java.util.Set;
public class XmlExampleGenerator {
protected final Logger LOGGER = LoggerFactory.getLogger(XmlExampleGenerator.class);
public static String NEWLINE = "\n";
public static String TAG_START = "<";
public static String CLOSE_TAG = ">";
@ -163,45 +173,44 @@ public class XmlExampleGenerator {
return sb.toString();
}
/**
* Get the example string value for the given Property.
*
* If an example value was not provided in the specification, a default will be generated.
*
* @param property Property to get example string for
*
* @return Example String
*/
protected String getExample(Property property) {
if (property instanceof DateTimeProperty) {
if (property.getExample() != null) {
return property.getExample().toString();
} else {
return "2000-01-23T04:56:07.000Z";
}
} else if (property instanceof StringProperty) {
if (property.getExample() != null) {
return property.getExample().toString();
} else {
return "string";
}
if (property.getExample() != null) {
return property.getExample().toString();
} else if (property instanceof DateTimeProperty) {
return "2000-01-23T04:56:07.000Z";
} else if (property instanceof DateProperty) {
if (property.getExample() != null) {
return property.getExample().toString();
} else {
return "2000-01-23";
}
} else if (property instanceof IntegerProperty) {
if (property.getExample() != null) {
return property.getExample().toString();
} else {
return "0";
}
return "2000-01-23";
} else if (property instanceof BooleanProperty) {
if (property.getExample() != null) {
return property.getExample().toString();
} else {
return "true";
}
return "true";
} else if (property instanceof LongProperty) {
if (property.getExample() != null) {
return property.getExample().toString();
} else {
return "123456";
}
return "123456789";
} else if (property instanceof DoubleProperty) { // derived from DecimalProperty so make sure this is first
return "3.149";
} else if (property instanceof DecimalProperty) {
return "1.3579";
} else if (property instanceof PasswordProperty) {
return "********";
} else if (property instanceof UUIDProperty) {
return "046b6c7f-0b8a-43b9-b35d-6489e6daee91";
// do these last in case the specific types above are derived from these classes
} else if (property instanceof StringProperty) {
return "aeiou";
} else if (property instanceof BaseIntegerProperty) {
return "123";
} else if (property instanceof AbstractNumericProperty) {
return "1.23";
}
return "not implemented " + property;
LOGGER.warn("default example value not implemented for " + property);
return "";
}
@SuppressWarnings("static-method")

View File

@ -8,34 +8,71 @@ import org.slf4j.LoggerFactory;
import java.io.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
/**
* Presents a processing utility for parsing and evaluating files containing common ignore patterns. (.swagger-codegen-ignore)
*/
public class CodegenIgnoreProcessor {
private static final Logger LOGGER = LoggerFactory.getLogger(CodegenIgnoreProcessor.class);
private final String outputPath;
private File ignoreFile = null;
private List<Rule> exclusionRules = new ArrayList<>();
private List<Rule> inclusionRules = new ArrayList<>();
public CodegenIgnoreProcessor(String outputPath) {
this.outputPath = outputPath;
final File directory = new File(outputPath);
if(directory.exists() && directory.isDirectory()){
final File codegenIgnore = new File(directory, ".swagger-codegen-ignore");
if(codegenIgnore.exists() && codegenIgnore.isFile()){
try {
loadCodegenRules(codegenIgnore);
} catch (IOException e) {
LOGGER.error("Could not process .swagger-codegen-ignore.", e.getMessage());
}
} else {
// log info message
LOGGER.info("No .swagger-codegen-ignore file found.");
}
/**
* Loads the default ignore file (.swagger-codegen-ignore) from the specified path.
*
* @param baseDirectory The base directory of the files to be processed. This contains the ignore file.
*/
public CodegenIgnoreProcessor(final String baseDirectory) {
this(baseDirectory, ".swagger-codegen-ignore");
}
/**
* Loads the specified ignore file by name ([ignoreFile]) from the specified path.
*
* @param baseDirectory The base directory of the files to be processed. This contains the ignore file.
* @param ignoreFile The file containing ignore patterns.
*/
@SuppressWarnings("WeakerAccess")
public CodegenIgnoreProcessor(final String baseDirectory, final String ignoreFile) {
final File directory = new File(baseDirectory);
final File targetIgnoreFile = new File(directory, ignoreFile);
if (directory.exists() && directory.isDirectory()) {
loadFromFile(targetIgnoreFile);
} else {
LOGGER.warn("Directory does not exist, or is inaccessible. No file will be evaluated.");
}
}
void loadCodegenRules(File codegenIgnore) throws IOException {
/**
* Constructs an instance of {@link CodegenIgnoreProcessor} from an ignore file defined by {@code targetIgnoreFile}.
*
* @param targetIgnoreFile The ignore file location.
*/
public CodegenIgnoreProcessor(final File targetIgnoreFile) {
loadFromFile(targetIgnoreFile);
}
private void loadFromFile(File targetIgnoreFile) {
if (targetIgnoreFile.exists() && targetIgnoreFile.isFile()) {
try {
loadCodegenRules(targetIgnoreFile);
this.ignoreFile = targetIgnoreFile;
} catch (IOException e) {
LOGGER.error(String.format("Could not process %s.", targetIgnoreFile.getName()), e.getMessage());
}
} else {
// log info message
LOGGER.info(String.format("No %s file found.", targetIgnoreFile.getName()));
}
}
void loadCodegenRules(final File codegenIgnore) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(codegenIgnore))) {
String line;
@ -61,8 +98,17 @@ public class CodegenIgnoreProcessor {
}
}
public boolean allowsFile(File targetFile) {
File file = new File(new File(this.outputPath).toURI().relativize(targetFile.toURI()).getPath());
/**
* Determines whether or not a file defined by {@code toEvaluate} is allowed,
* under the exclusion rules from the ignore file being processed.
*
* @param targetFile The file to check against exclusion rules from the ignore file.
* @return {@code false} if file matches any pattern in the ignore file (disallowed), otherwise {@code true} (allowed).
*/
public boolean allowsFile(final File targetFile) {
if(this.ignoreFile == null) return true;
File file = new File(this.ignoreFile.getParentFile().toURI().relativize(targetFile.toURI()).getPath());
Boolean directoryExcluded = false;
Boolean exclude = false;
if(exclusionRules.size() == 0 && inclusionRules.size() == 0) {
@ -124,10 +170,23 @@ public class CodegenIgnoreProcessor {
return Boolean.FALSE.equals(exclude);
}
/**
* Allows a consumer to manually inspect explicit "inclusion rules". That is, patterns in the ignore file which have been negated.
*
* @return A {@link ImmutableList#copyOf(Collection)} of rules which possibly negate exclusion rules in the ignore file.
*/
public List<Rule> getInclusionRules() {
return ImmutableList.copyOf(inclusionRules);
}
/**
* Allows a consumer to manually inspect all "exclusion rules". That is, patterns in the ignore file which represent
* files and directories to be excluded, unless explicitly overridden by {@link CodegenIgnoreProcessor#getInclusionRules()} rules.
*
* NOTE: Existence in this list doesn't mean a file is excluded. The rule can be overridden by {@link CodegenIgnoreProcessor#getInclusionRules()} rules.
*
* @return A {@link ImmutableList#copyOf(Collection)} of rules which define exclusions by patterns in the ignore file.
*/
public List<Rule> getExclusionRules() {
return ImmutableList.copyOf(exclusionRules);
}

View File

@ -51,6 +51,8 @@ public abstract class Rule {
* Example: **\/*.bak excludes all backup. Adding !/test.bak will include test.bak in the project root.
* <p>
* NOTE: It is not possible to re-include a file if a parent directory of that file is excluded.
*
* @return {@code true} if the rule is negated (inverse), otherwise {@code false} (normal).
*/
public Boolean getNegated() {
return this.syntax != null && this.syntax.size() > 0 && this.syntax.get(0).getToken() == IgnoreLineParser.Token.NEGATE;

View File

@ -27,6 +27,8 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
protected String packageCompany = "Swagger";
protected String packageCopyright = "No Copyright";
protected String interfacePrefix = "I";
protected String sourceFolder = "src";
// TODO: Add option for test folder output location. Nice to allow e.g. ./test instead of ./src.
@ -254,6 +256,19 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES)) {
setOptionalEmitDefaultValue(Boolean.valueOf(additionalProperties.get(CodegenConstants.OPTIONAL_EMIT_DEFAULT_VALUES).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.INTERFACE_PREFIX)) {
String useInterfacePrefix = additionalProperties.get(CodegenConstants.INTERFACE_PREFIX).toString();
if("false".equals(useInterfacePrefix.toLowerCase())) {
setInterfacePrefix("");
} else if(!"true".equals(useInterfacePrefix.toLowerCase())) {
// NOTE: if user passes "true" explicitly, we use the default I- prefix. The other supported case here is a custom prefix.
setInterfacePrefix(sanitizeName(useInterfacePrefix));
}
}
// This either updates additionalProperties with the above fixes, or sets the default if the option was not specified.
additionalProperties.put(CodegenConstants.INTERFACE_PREFIX, interfacePrefix);
}
@Override
@ -401,10 +416,13 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
}
return name;
}
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@ -466,7 +484,13 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
if (p instanceof StringProperty) {
StringProperty dp = (StringProperty) p;
if (dp.getDefault() != null) {
return "\"" + dp.getDefault() + "\"";
String _default = dp.getDefault();
if (dp.getEnum() == null) {
return "\"" + _default + "\"";
} else {
// convert to enum var name later in postProcessModels
return _default;
}
}
} else if (p instanceof BooleanProperty) {
BooleanProperty dp = (BooleanProperty) p;
@ -613,8 +637,20 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
this.sourceFolder = sourceFolder;
}
public String getInterfacePrefix() {
return interfacePrefix;
}
public void setInterfacePrefix(final String interfacePrefix) {
this.interfacePrefix = interfacePrefix;
}
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "Empty";
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return camelize(getSymbolName(name));

View File

@ -52,6 +52,15 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
protected String groupId = "io.swagger";
protected String artifactId = "swagger-java";
protected String artifactVersion = "1.0.0";
protected String artifactUrl = "https://github.com/swagger-api/swagger-codegen";
protected String artifactDescription = "Swagger Java";
protected String developerName = "Swagger";
protected String developerEmail = "apiteam@swagger.io";
protected String developerOrganization = "Swagger";
protected String developerOrganizationUrl = "http://swagger.io";
protected String scmConnection = "scm:git:git@github.com:swagger-api/swagger-codegen.git";
protected String scmDeveloperConnection = "scm:git:git@github.com:swagger-api/swagger-codegen.git";
protected String scmUrl = "https://github.com/swagger-api/swagger-codegen";
protected String licenseName = "Unlicense";
protected String licenseUrl = "http://unlicense.org";
protected String projectFolder = "src" + File.separator + "main";
@ -118,6 +127,15 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
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));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_URL, CodegenConstants.ARTIFACT_URL_DESC));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_DESCRIPTION, CodegenConstants.ARTIFACT_DESCRIPTION_DESC));
cliOptions.add(new CliOption(CodegenConstants.SCM_CONNECTION, CodegenConstants.SCM_CONNECTION_DESC));
cliOptions.add(new CliOption(CodegenConstants.SCM_DEVELOPER_CONNECTION, CodegenConstants.SCM_DEVELOPER_CONNECTION_DESC));
cliOptions.add(new CliOption(CodegenConstants.SCM_URL, CodegenConstants.SCM_URL_DESC));
cliOptions.add(new CliOption(CodegenConstants.DEVELOPER_NAME, CodegenConstants.DEVELOPER_NAME_DESC));
cliOptions.add(new CliOption(CodegenConstants.DEVELOPER_EMAIL, CodegenConstants.DEVELOPER_EMAIL_DESC));
cliOptions.add(new CliOption(CodegenConstants.DEVELOPER_ORGANIZATION, CodegenConstants.DEVELOPER_ORGANIZATION_DESC));
cliOptions.add(new CliOption(CodegenConstants.DEVELOPER_ORGANIZATION_URL, CodegenConstants.DEVELOPER_ORGANIZATION_URL_DESC));
cliOptions.add(new CliOption(CodegenConstants.LICENSE_NAME, CodegenConstants.LICENSE_NAME_DESC));
cliOptions.add(new CliOption(CodegenConstants.LICENSE_URL, CodegenConstants.LICENSE_URL_DESC));
cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC));
@ -191,6 +209,60 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
}
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_URL)) {
this.setArtifactUrl((String) additionalProperties.get(CodegenConstants.ARTIFACT_URL));
} else {
additionalProperties.put(CodegenConstants.ARTIFACT_URL, artifactUrl);
}
if (additionalProperties.containsKey(CodegenConstants.ARTIFACT_DESCRIPTION)) {
this.setArtifactDescription((String) additionalProperties.get(CodegenConstants.ARTIFACT_DESCRIPTION));
} else {
additionalProperties.put(CodegenConstants.ARTIFACT_DESCRIPTION, artifactDescription);
}
if (additionalProperties.containsKey(CodegenConstants.SCM_CONNECTION)) {
this.setScmConnection((String) additionalProperties.get(CodegenConstants.SCM_CONNECTION));
} else {
additionalProperties.put(CodegenConstants.SCM_CONNECTION, scmConnection);
}
if (additionalProperties.containsKey(CodegenConstants.SCM_DEVELOPER_CONNECTION)) {
this.setScmDeveloperConnection((String) additionalProperties.get(CodegenConstants.SCM_DEVELOPER_CONNECTION));
} else {
additionalProperties.put(CodegenConstants.SCM_DEVELOPER_CONNECTION, scmDeveloperConnection);
}
if (additionalProperties.containsKey(CodegenConstants.SCM_URL)) {
this.setScmUrl((String) additionalProperties.get(CodegenConstants.SCM_URL));
} else {
additionalProperties.put(CodegenConstants.SCM_URL, scmUrl);
}
if (additionalProperties.containsKey(CodegenConstants.DEVELOPER_NAME)) {
this.setDeveloperName((String) additionalProperties.get(CodegenConstants.DEVELOPER_NAME));
} else {
additionalProperties.put(CodegenConstants.DEVELOPER_NAME, developerName);
}
if (additionalProperties.containsKey(CodegenConstants.DEVELOPER_EMAIL)) {
this.setDeveloperEmail((String) additionalProperties.get(CodegenConstants.DEVELOPER_EMAIL));
} else {
additionalProperties.put(CodegenConstants.DEVELOPER_EMAIL, developerEmail);
}
if (additionalProperties.containsKey(CodegenConstants.DEVELOPER_ORGANIZATION)) {
this.setDeveloperOrganization((String) additionalProperties.get(CodegenConstants.DEVELOPER_ORGANIZATION));
} else {
additionalProperties.put(CodegenConstants.DEVELOPER_ORGANIZATION, developerOrganization);
}
if (additionalProperties.containsKey(CodegenConstants.DEVELOPER_ORGANIZATION_URL)) {
this.setDeveloperOrganizationUrl((String) additionalProperties.get(CodegenConstants.DEVELOPER_ORGANIZATION_URL));
} else {
additionalProperties.put(CodegenConstants.DEVELOPER_ORGANIZATION_URL, developerOrganizationUrl);
}
if (additionalProperties.containsKey(CodegenConstants.LICENSE_NAME)) {
this.setLicenseName((String) additionalProperties.get(CodegenConstants.LICENSE_NAME));
} else {
@ -336,6 +408,9 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@ -434,11 +509,22 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
@Override
public String toModelName(final String name) {
final String sanitizedName = sanitizeName(modelNamePrefix + name + modelNameSuffix);
final String sanitizedName = sanitizeName(name);
String nameWithPrefixSuffix = sanitizedName;
if (!StringUtils.isEmpty(modelNamePrefix)) {
// add '_' so that model name can be camelized correctly
nameWithPrefixSuffix = modelNamePrefix + "_" + nameWithPrefixSuffix;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
// add '_' so that model name can be camelized correctly
nameWithPrefixSuffix = nameWithPrefixSuffix + "_" + modelNameSuffix;
}
// camelize the model name
// phone_number => PhoneNumber
final String camelizedName = camelize(sanitizedName);
final String camelizedName = camelize(nameWithPrefixSuffix);
// model name cannot use reserved keyword, e.g. return
if (isReservedWord(camelizedName)) {
@ -448,7 +534,7 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
}
// model name starts with number
if (name.matches("^\\d.*")) {
if (camelizedName.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;
@ -815,6 +901,10 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
return "EMPTY";
}
// for symbol, e.g. $, #
if (getSymbolName(value) != null) {
return getSymbolName(value).toUpperCase();
@ -929,6 +1019,42 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
this.artifactVersion = artifactVersion;
}
public void setArtifactUrl(String artifactUrl) {
this.artifactUrl = artifactUrl;
}
public void setArtifactDescription(String artifactDescription) {
this.artifactDescription = artifactDescription;
}
public void setScmConnection(String scmConnection) {
this.scmConnection = scmConnection;
}
public void setScmDeveloperConnection(String scmDeveloperConnection) {
this.scmDeveloperConnection = scmDeveloperConnection;
}
public void setScmUrl(String scmUrl) {
this.scmUrl = scmUrl;
}
public void setDeveloperName(String developerName) {
this.developerName = developerName;
}
public void setDeveloperEmail(String developerEmail) {
this.developerEmail = developerEmail;
}
public void setDeveloperOrganization(String developerOrganization) {
this.developerOrganization = developerOrganization;
}
public void setDeveloperOrganizationUrl(String developerOrganizationUrl) {
this.developerOrganizationUrl = developerOrganizationUrl;
}
public void setLicenseName(String licenseName) {
this.licenseName = licenseName;
}
@ -1008,4 +1134,22 @@ public abstract class AbstractJavaCodegen extends DefaultCodegen implements Code
return escapeText(pattern);
}
public boolean convertPropertyToBoolean(String propertyKey) {
boolean booleanValue = false;
if (additionalProperties.containsKey(propertyKey)) {
booleanValue = Boolean.valueOf(additionalProperties.get(propertyKey).toString());
}
return booleanValue;
}
public void writePropertyBack(String propertyKey, boolean value) {
additionalProperties.put(propertyKey, value);
}
@Override
public String sanitizeTag(String tag) {
return camelize(sanitizeName(tag));
}
}

View File

@ -1,6 +1,7 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.codegen.languages.features.BeanValidationFeatures;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
@ -10,7 +11,7 @@ import org.slf4j.LoggerFactory;
import java.util.*;
public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen {
public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen implements BeanValidationFeatures {
/**
* Name of the sub-directory in "src/main/resource" where to find the
* Mustache template for the JAX-RS Codegen.
@ -19,6 +20,9 @@ public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen
protected String implFolder = "src/main/java";
protected String testResourcesFolder = "src/test/resources";
protected String title = "Swagger Server";
protected boolean useBeanValidation = true;
static Logger LOGGER = LoggerFactory.getLogger(AbstractJavaJAXRSServerCodegen.class);
public AbstractJavaJAXRSServerCodegen()
@ -40,6 +44,8 @@ public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen
cliOptions.add(new CliOption(CodegenConstants.IMPL_FOLDER, CodegenConstants.IMPL_FOLDER_DESC));
cliOptions.add(new CliOption("title", "a title describing the application"));
cliOptions.add(CliOption.newBoolean(USE_BEANVALIDATION, "Use BeanValidation API annotations"));
}
@ -60,6 +66,15 @@ public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen
if (additionalProperties.containsKey(CodegenConstants.IMPL_FOLDER)) {
implFolder = (String) additionalProperties.get(CodegenConstants.IMPL_FOLDER);
}
if (additionalProperties.containsKey(USE_BEANVALIDATION)) {
this.setUseBeanValidation(convertPropertyToBoolean(USE_BEANVALIDATION));
}
if (useBeanValidation) {
writePropertyBack(USE_BEANVALIDATION, useBeanValidation);
}
}
@Override
@ -204,4 +219,9 @@ public abstract class AbstractJavaJAXRSServerCodegen extends AbstractJavaCodegen
private String implFileFolder(String output) {
return outputFolder + "/" + output + "/" + apiPackage().replace('.', '/');
}
public void setUseBeanValidation(boolean useBeanValidation) {
this.useBeanValidation = useBeanValidation;
}
}

View File

@ -251,8 +251,11 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
.replaceAll(regLastPathSeparator+ "$", "");
}
@Override
public String escapeReservedWord(String name) {
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@ -589,6 +592,10 @@ public abstract class AbstractPhpCodegen extends DefaultCodegen implements Codeg
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "EMPTY";
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return (getSymbolName(name)).toUpperCase();

View File

@ -67,7 +67,10 @@ public abstract class AbstractScalaCodegen extends DefaultCodegen {
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}

View File

@ -112,7 +112,6 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
}
}
@Override
public CodegenType getTag() {
return CodegenType.CLIENT;
@ -120,6 +119,9 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@ -155,8 +157,8 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
@Override
public String toVarName(String name) {
// should be the same as variable name
return getNameUsingModelPropertyNaming(name);
// should be the same as variable name
return getNameUsingModelPropertyNaming(name);
}
@Override
@ -291,6 +293,10 @@ public abstract class AbstractTypeScriptClientCodegen extends DefaultCodegen imp
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "Empty";
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return camelize(getSymbolName(name));

View File

@ -154,6 +154,9 @@ public class AkkaScalaClientCodegen extends AbstractScalaCodegen implements Code
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "`" + name + "`";
}

View File

@ -119,7 +119,10 @@ public class AndroidClientCodegen extends DefaultCodegen implements CodegenConfi
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}

View File

@ -14,8 +14,6 @@ import static java.util.UUID.randomUUID;
public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
protected String sourceFolder = "src" + File.separator + packageName;
private final String packageGuid = "{" + randomUUID().toString().toUpperCase() + "}";
@SuppressWarnings("hiding")
@ -24,6 +22,7 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
public AspNetCoreServerCodegen() {
super();
setSourceFolder("src");
outputFolder = "generated-code" + File.separator + this.getName();
modelTemplateFiles.put("model.mustache", ".cs");
@ -91,38 +90,53 @@ public class AspNetCoreServerCodegen extends AbstractCSharpCodegen {
apiPackage = packageName + ".Controllers";
modelPackage = packageName + ".Models";
String packageFolder = sourceFolder + File.separator + packageName;
supportingFiles.add(new SupportingFile("NuGet.Config", "", "NuGet.Config"));
supportingFiles.add(new SupportingFile("global.json", "", "global.json"));
supportingFiles.add(new SupportingFile("build.sh.mustache", "", "build.sh"));
supportingFiles.add(new SupportingFile("build.bat.mustache", "", "build.bat"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("Solution.mustache", "", this.packageName + ".sln"));
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("Dockerfile.mustache", packageFolder, "Dockerfile"));
supportingFiles.add(new SupportingFile("gitignore", packageFolder, ".gitignore"));
supportingFiles.add(new SupportingFile("appsettings.json", packageFolder, "appsettings.json"));
supportingFiles.add(new SupportingFile("project.json.mustache", this.sourceFolder, "project.json"));
supportingFiles.add(new SupportingFile("Startup.mustache", this.sourceFolder, "Startup.cs"));
supportingFiles.add(new SupportingFile("Program.mustache", this.sourceFolder, "Program.cs"));
supportingFiles.add(new SupportingFile("web.config", this.sourceFolder, "web.config"));
supportingFiles.add(new SupportingFile("project.json.mustache", packageFolder, "project.json"));
supportingFiles.add(new SupportingFile("Startup.mustache", packageFolder, "Startup.cs"));
supportingFiles.add(new SupportingFile("Program.mustache", packageFolder, "Program.cs"));
supportingFiles.add(new SupportingFile("web.config", packageFolder, "web.config"));
supportingFiles.add(new SupportingFile("Project.xproj.mustache", this.sourceFolder, this.packageName + ".xproj"));
supportingFiles.add(new SupportingFile("Project.xproj.mustache", packageFolder, this.packageName + ".xproj"));
supportingFiles.add(new SupportingFile("Properties" + File.separator + "launchSettings.json", this.sourceFolder + File.separator + "Properties", "launchSettings.json"));
supportingFiles.add(new SupportingFile("Properties" + File.separator + "launchSettings.json", packageFolder + 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"));
supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "README.md", packageFolder + File.separator + "wwwroot", "README.md"));
supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "index.html", packageFolder + File.separator + "wwwroot", "index.html"));
supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "web.config", packageFolder + File.separator + "wwwroot", "web.config"));
}
@Override
public void setSourceFolder(final String sourceFolder) {
if(sourceFolder == null) {
LOGGER.warn("No sourceFolder specified, using default");
this.sourceFolder = "src" + File.separator + this.packageName;
} else if(!sourceFolder.equals("src") && !sourceFolder.startsWith("src")) {
LOGGER.warn("ASP.NET Core requires source code exists under src. Adjusting.");
this.sourceFolder = "src" + File.separator + sourceFolder;
} else {
this.sourceFolder = sourceFolder;
}
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + "Controllers";
return outputFolder + File.separator + sourceFolder + File.separator + packageName + File.separator + "Controllers";
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + "Models";
return outputFolder + File.separator + sourceFolder + File.separator + packageName + File.separator + "Models";
}
@Override

View File

@ -0,0 +1,662 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.properties.*;
import io.swagger.models.parameters.*;
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.MapProperty;
import io.swagger.models.properties.Property;
import org.apache.commons.lang3.StringEscapeUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.io.File;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.node.ObjectNode;
public class BashClientCodegen extends DefaultCodegen implements CodegenConfig {
protected String apiVersion = "1.0.0";
protected String curlOptions;
protected boolean processMarkdown = false;
protected String scriptName = "client.sh";
protected boolean generateBashCompletion = false;
protected boolean generateZshCompletion = false;
protected String hostEnvironmentVariable;
protected String basicAuthEnvironmentVariable;
protected String apiKeyAuthEnvironmentVariable;
public static final String CURL_OPTIONS = "curlOptions";
public static final String PROCESS_MARKDOWN = "processMarkdown";
public static final String SCRIPT_NAME = "scriptName";
public static final String
GENERATE_BASH_COMPLETION = "generateBashCompletion";
public static final String
GENERATE_ZSH_COMPLETION = "generateZshCompletion";
public static final String
HOST_ENVIRONMENT_VARIABLE_NAME = "hostEnvironmentVariable";
public static final String
BASIC_AUTH_ENVIRONMENT_VARIABLE_NAME = "basicAuthEnvironmentVariable";
public static final String
APIKEY_AUTH_ENVIRONMENT_VARIABLE_NAME = "apiKeyAuthEnvironmentVariable";
/**
* Configures the type of generator.
*
* @return the CodegenType for this generator
* @see io.swagger.codegen.CodegenType
*/
public CodegenType getTag() {
return CodegenType.CLIENT;
}
/**
* 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 "bash";
}
/**
* 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 Bash client script based on cURL.";
}
public BashClientCodegen() {
super();
/**
* Set the output folder here
*/
outputFolder = "generated-code/bash";
/**
* No model files.
*/
modelTemplateFiles.clear();
/**
* No API files.
*/
apiTemplateFiles.clear();
/**
* Templates location for client script and bash completion template.
*/
embeddedTemplateDir = templateDir = "bash";
/**
* Allow the user to force the script to always include certain cURL
* comamnds
*/
cliOptions.add(CliOption.newString(CURL_OPTIONS, "Default cURL options"));
cliOptions.add(CliOption.newBoolean(PROCESS_MARKDOWN,
"Convert all Markdown Markup into terminal formatting"));
cliOptions.add(CliOption.newString(SCRIPT_NAME,
"The name of the script that will be generated "+
"(e.g. petstore-cli)"));
cliOptions.add(CliOption.newBoolean(GENERATE_BASH_COMPLETION,
"Whether to generate the Bash completion script"));
cliOptions.add(CliOption.newBoolean(GENERATE_ZSH_COMPLETION,
"Whether to generate the Zsh completion script"));
cliOptions.add(CliOption.newString(HOST_ENVIRONMENT_VARIABLE_NAME,
"Name of environment variable where host can be defined "+
"(e.g. PETSTORE_HOST='http://petstore.swagger.io:8080')"));
cliOptions.add(CliOption.newString(BASIC_AUTH_ENVIRONMENT_VARIABLE_NAME,
"Name of environment variable where username and password "
+
"can be defined (e.g. PETSTORE_CREDS='username:password')"));
cliOptions.add(CliOption.newBoolean(APIKEY_AUTH_ENVIRONMENT_VARIABLE_NAME,
"Name of environment variable where API key "
+
"can be defined (e.g. PETSTORE_APIKEY='kjhasdGASDa5asdASD')"));
/**
* Bash reserved words.
*/
reservedWords = new HashSet<String> (
Arrays.asList(
"case",
"do",
"done",
"elif",
"else",
"esac",
"fi",
"for",
"function",
"if",
"in",
"select",
"then",
"time",
"until",
"while")
);
typeMapping.clear();
typeMapping.put("array", "array");
typeMapping.put("map", "map");
typeMapping.put("List", "array");
typeMapping.put("boolean", "boolean");
typeMapping.put("string", "string");
typeMapping.put("int", "integer");
typeMapping.put("float", "float");
typeMapping.put("number", "integer");
typeMapping.put("DateTime", "string");
typeMapping.put("long", "integer");
typeMapping.put("short", "integer");
typeMapping.put("char", "string");
typeMapping.put("double", "float");
typeMapping.put("object", "map");
typeMapping.put("integer", "integer");
typeMapping.put("ByteArray", "string");
typeMapping.put("binary", "binary");
/**
* Additional Properties. These values can be passed to the templates and
* are available in models, apis, and supporting files.
*/
additionalProperties.put("apiVersion", apiVersion);
/**
* Language Specific Primitives. These types will not trigger imports by
* the client generator
*/
languageSpecificPrimitives = new HashSet<String>();
}
@Override
public void processOpts() {
super.processOpts();
String curlopts = "";
if (additionalProperties.containsKey(CURL_OPTIONS)) {
setCurlOptions(additionalProperties.get(CURL_OPTIONS).toString());
additionalProperties.put("x-codegen-curl-options", curlopts);
}
if (additionalProperties.containsKey(PROCESS_MARKDOWN)) {
setProcessMarkdown(
Boolean.parseBoolean(
additionalProperties.get(PROCESS_MARKDOWN).toString()));
}
if (additionalProperties.containsKey(GENERATE_BASH_COMPLETION)) {
setGenerateBashCompletion(
Boolean.parseBoolean(
additionalProperties.get(GENERATE_BASH_COMPLETION).toString()));
}
if (additionalProperties.containsKey(GENERATE_ZSH_COMPLETION)) {
setGenerateZshCompletion(
Boolean.parseBoolean(
additionalProperties.get(GENERATE_ZSH_COMPLETION).toString()));
}
if (additionalProperties.containsKey(SCRIPT_NAME)) {
setScriptName(additionalProperties.get(SCRIPT_NAME).toString());
}
additionalProperties.put("x-codegen-script-name", scriptName);
if (additionalProperties.containsKey(HOST_ENVIRONMENT_VARIABLE_NAME)) {
setHostEnvironmentVariable(
additionalProperties.get(HOST_ENVIRONMENT_VARIABLE_NAME).toString());
additionalProperties.put("x-codegen-host-env", hostEnvironmentVariable);
}
if (additionalProperties.containsKey(BASIC_AUTH_ENVIRONMENT_VARIABLE_NAME)) {
setBasicAuthEnvironmentVariable(
additionalProperties.get(BASIC_AUTH_ENVIRONMENT_VARIABLE_NAME).toString());
additionalProperties.put("x-codegen-basicauth-env", basicAuthEnvironmentVariable);
}
if (additionalProperties.containsKey(APIKEY_AUTH_ENVIRONMENT_VARIABLE_NAME)) {
setApiKeyAuthEnvironmentVariable(
additionalProperties.get(APIKEY_AUTH_ENVIRONMENT_VARIABLE_NAME).toString());
additionalProperties.put("x-codegen-apikey-env", apiKeyAuthEnvironmentVariable);
}
supportingFiles.add(new SupportingFile(
"client.mustache", "", scriptName));
supportingFiles.add(new SupportingFile(
"bash-completion.mustache", "", scriptName+".bash-completion"));
supportingFiles.add(new SupportingFile(
"zsh-completion.mustache", "", "_"+scriptName));
supportingFiles.add(new SupportingFile(
"README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile(
"Dockerfile.mustache", "", "Dockerfile"));
}
public void setCurlOptions(String curlOptions) {
this.curlOptions = curlOptions;
}
public void setProcessMarkdown(boolean processMarkdown) {
this.processMarkdown = processMarkdown;
}
public void setScriptName(String scriptName) {
this.scriptName = scriptName;
}
public void setGenerateBashCompletion(boolean generateBashCompletion) {
this.generateBashCompletion = generateBashCompletion;
}
public void setGenerateZshCompletion(boolean generateZshCompletion) {
this.generateZshCompletion = generateZshCompletion;
}
public void setHostEnvironmentVariable(String hostEnvironmentVariable) {
this.hostEnvironmentVariable = hostEnvironmentVariable;
}
public void setBasicAuthEnvironmentVariable(String
basicAuthEnvironmentVariable) {
this.basicAuthEnvironmentVariable = basicAuthEnvironmentVariable;
}
public void setApiKeyAuthEnvironmentVariable(String
apiKeyAuthEnvironmentVariable) {
this.apiKeyAuthEnvironmentVariable = apiKeyAuthEnvironmentVariable;
}
/**
* 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; // add an underscore to the name
}
/**
* Location to write model files. You can use the modelPackage() as defined
* when the class is instantiated.
*/
public String modelFileFolder() {
return outputFolder;
}
/**
* Location to write api files. You can use the apiPackage() as defined when
* the class is instantiated.
*/
@Override
public String apiFileFolder() {
return outputFolder;
}
/**
* 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 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);
}
/**
* 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 type;
}
else
type = swaggerType;
return toModelName(type);
}
/**
* Convert Swagger Parameter object to Codegen Parameter object
*
* @param param Swagger parameter object
* @param imports set of imports for library/package/module
* @return Codegen Parameter object
*/
@Override
public CodegenParameter fromParameter(Parameter param, Set<String> imports) {
CodegenParameter p = super.fromParameter(param, imports);
if(param instanceof BodyParameter) {
Model model = ((BodyParameter)param).getSchema();
}
else if(param instanceof SerializableParameter) {
/**
* Currently it's not possible to specify in the codegen other collection
* formats than 'multi'
*/
SerializableParameter sparam = (SerializableParameter)param;
if( sparam.getCollectionFormat() != null
&& !sparam.getCollectionFormat().isEmpty()) {
String collectionFormat = sparam.getCollectionFormat();
if(sparam.isExclusiveMaximum()!=null && sparam.isExclusiveMaximum()) {
p.vendorExtensions.put("x-codegen-collection-max-items",
sparam.getMaxItems());
}
if(sparam.isExclusiveMinimum()!=null && sparam.isExclusiveMinimum()) {
p.vendorExtensions.put("x-codegen-collection-min-items",
sparam.getMinItems());
}
if( (collectionFormat.equals("multi"))
&& (param.getIn().equals("query")) ) {
/**
* 'multi' is only supported for query parameters
*/
p.vendorExtensions.put("x-codegen-collection-multi", true);
}
else if(collectionFormat.equals("csv")) {
p.vendorExtensions.put("x-codegen-collection-csv", true);
}
else if(collectionFormat.equals("ssv")) {
p.vendorExtensions.put("x-codegen-collection-ssv", true);
}
else if(collectionFormat.equals("tsv")) {
p.vendorExtensions.put("x-codegen-collection-tsv", true);
}
else if(collectionFormat.equals("pipes")) {
p.vendorExtensions.put("x-codegen-collection-pipes", true);
}
else {
/** Unsupported collection format */
}
}
}
return p;
}
/**
* Override with any special text escaping logic
*/
@SuppressWarnings("static-method")
public String escapeText(String input) {
if (input == null) {
return input;
}
/**
* Trim the input text always.
*/
String result = input.trim();
/**
* remove standalone '\'
*
* replace " with \"
* outter unescape to retain the original multi-byte characters
*/
result = escapeUnsafeCharacters(
StringEscapeUtils.unescapeJava(
StringEscapeUtils.escapeJava(result).replace("\\/", "/"))
.replace("\\", "\\\\")
.replace("\"", "\\\""));
if(this.processMarkdown) {
/**
* Convert markdown strong **Bold text** and __Bold text__
* to bash bold control sequences (tput bold)
*/
result = result.replaceAll("(?m)(^|\\s)\\*{2}([\\w\\d ]+)\\*{2}($|\\s)",
"\\$\\(tput bold\\) $2 \\$\\(tput sgr0\\)");
result = result.replaceAll("(?m)(^|\\s)_{2}([\\w\\d ]+)_{2}($|\\s)",
"\\$\\(tput bold\\) $2 \\$\\(tput sgr0\\)");
/**
* Convert markdown *Italics text* and _Italics text_ to bash dim
* control sequences (tput dim)
*/
result = result.replaceAll("(?m)(^|\\s)\\*{1}([\\w\\d ]+)\\*{1}($|\\s)",
"\\$\\(tput dim\\) $2 \\$\\(tput sgr0\\)");
result = result.replaceAll("(?m)(^|\\s)_{1}([\\w\\d ]+)_{1}($|\\s)",
"\\$\\(tput dim\\) $2 \\$\\(tput sgr0\\)");
/**
* Convert all markdown section 1 level headers with bold
*/
result = result.replaceAll("(?m)^\\#\\s+(.+)$",
"\n\\$\\(tput bold\\)\\$\\(tput setaf 7\\)"
+"$1\\$\\(tput sgr0\\)");
/**
* Convert all markdown section 2 level headers with bold
*/
result = result.replaceAll("(?m)^\\#\\#\\s+(.+)$",
"\n\\$\\(tput bold\\)\\$\\(tput setaf 7\\)"
+"$1\\$\\(tput sgr0\\)");
/**
* Convert all markdown section 3 level headers with bold
*/
result = result.replaceAll("(?m)^\\#\\#\\#\\s+(.+)$",
"\n\\$\\(tput bold\\)\\$\\(tput setaf 7\\)"
+"$1\\$\\(tput sgr0\\)");
/**
* Convert all markdown code blocks into --- delimited sections
*/
result = result.replaceAll("(?m)\\s*```.*$",
"\n---");
result = result.replaceAll("(?m)\\s*\\'\\'\\'.*$",
"\n---");
/**
* Remove any trailing new line at the end of the string
*/
result = result.replaceAll("\\s+$", "");
}
return result;
}
@Override
public String escapeQuotationMark(String input) {
return input;
}
/**
* Override with any special text escaping logic to handle unsafe
* characters so as to avoid code injection.
*
* @param input String to be cleaned up
* @return string with unsafe characters removed or escaped
*/
public String escapeUnsafeCharacters(String input) {
/**
* Replace backticks with normal single quotes.
*/
String result = input.replaceAll("`", "'");
return result;
}
@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);
/**
* Check if the operation has a Bash codegen specific description
* for help
*/
if(op.vendorExtensions.containsKey("x-bash-codegen-description")) {
String bash_description
= (String)op.vendorExtensions.get("x-bash-codegen-description");
op.vendorExtensions.put("x-bash-codegen-description",
escapeText(bash_description));
}
/**
* Check if operation has an 'x-code-samples' vendor extension with
* Shell example
*/
if(op.vendorExtensions.containsKey("x-code-samples")) {
List codesamples = (List)op.vendorExtensions.get("x-code-samples");
for (Object codesample : codesamples) {
ObjectNode codesample_object = (ObjectNode)codesample;
if((codesample_object.get("lang").asText()).equals("Shell")) {
op.vendorExtensions.put("x-bash-codegen-sample",
escapeUnsafeCharacters(
codesample_object.get("source").asText()));
}
}
}
for (CodegenParameter p : op.bodyParams) {
if(p.dataType != null && definitions.get(p.dataType) != null) {
/**
* If the operation produces Json and has nonempty example
* try to reformat it.
*/
if(operation.getConsumes() != null
&& operation.getConsumes().contains("application/json")
&& definitions.get(p.dataType).getExample() != null) {
ObjectMapper mapper = new ObjectMapper();
try {
p.vendorExtensions.put(
"x-codegen-body-example",
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(
definitions.get(p.dataType).getExample()));
}
catch(JsonProcessingException e) {
e.printStackTrace();
}
}
else {
/**
* Otherwise present whatever is provided as example
*/
p.vendorExtensions.put(
"x-codegen-body-example",
definitions.get(p.dataType).getExample());
}
}
}
return op;
}
/**
* Preprocess original properties from the Swagger definition where necessary.
*
* @param swagger [description]
*/
@Override
public void preprocessSwagger(Swagger swagger) {
super.preprocessSwagger(swagger);
if ("/".equals(swagger.getBasePath())) {
swagger.setBasePath("");
}
if(swagger.getInfo() != null
&& swagger.getInfo().getVendorExtensions()!=null) {
String bash_codegen_app_description
= (String)swagger.getInfo().getVendorExtensions()
.get("x-bash-codegen-description");
if(bash_codegen_app_description != null) {
bash_codegen_app_description
= escapeText(bash_codegen_app_description);
additionalProperties.put("x-bash-codegen-app-description",
bash_codegen_app_description);
}
}
}
}

View File

@ -1,6 +1,9 @@
package io.swagger.codegen.languages;
import com.google.common.collect.ImmutableMap;
import com.sun.org.apache.bcel.internal.classfile.Code;
import io.swagger.codegen.CodegenConstants;
import io.swagger.codegen.CodegenType;
import io.swagger.codegen.CodegenModel;
@ -45,6 +48,9 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
protected Map<Character, String> regexModifiers;
protected final Map<String, String> frameworks;
// By default, generated code is considered public
protected boolean nonPublicApi = Boolean.FALSE;
public CSharpClientCodegen() {
super();
modelTemplateFiles.put("model.mustache", ".cs");
@ -72,6 +78,10 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
CodegenConstants.OPTIONAL_PROJECT_GUID_DESC,
null);
addOption(CodegenConstants.INTERFACE_PREFIX,
CodegenConstants.INTERFACE_PREFIX_DESC,
interfacePrefix);
CliOption framework = new CliOption(
CodegenConstants.DOTNET_FRAMEWORK,
CodegenConstants.DOTNET_FRAMEWORK_DESC
@ -126,6 +136,18 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
CodegenConstants.PACKAGE_DESCRIPTION_DESC,
this.generatePropertyChanged);
// NOTE: This will reduce visibility of all public members in templates. Users can use InternalsVisibleTo
// https://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute(v=vs.110).aspx
// to expose to shared code if the generated code is not embedded into another project. Otherwise, users of codegen
// should rely on default public visibility.
addSwitch(CodegenConstants.NON_PUBLIC_API,
CodegenConstants.NON_PUBLIC_API_DESC,
this.nonPublicApi);
addSwitch(CodegenConstants.ALLOW_UNICODE_IDENTIFIERS,
CodegenConstants.ALLOW_UNICODE_IDENTIFIERS_DESC,
this.allowUnicodeIdentifiers);
regexModifiers = new HashMap<Character, String>();
regexModifiers.put('i', "IgnoreCase");
regexModifiers.put('m', "Multiline");
@ -228,6 +250,10 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
.get(CodegenConstants.OPTIONAL_ASSEMBLY_INFO).toString()));
}
if (additionalProperties.containsKey(CodegenConstants.NON_PUBLIC_API)) {
setNonPublicApi(Boolean.valueOf(additionalProperties.get(CodegenConstants.NON_PUBLIC_API).toString()));
}
final String testPackageName = testPackageName();
String packageFolder = sourceFolder + File.separator + packageName;
String clientPackageDir = packageFolder + File.separator + clientPackage;
@ -293,6 +319,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
if (optionalProjectFileFlag) {
supportingFiles.add(new SupportingFile("Solution.mustache", "", packageName + ".sln"));
supportingFiles.add(new SupportingFile("Project.mustache", packageFolder, packageName + ".csproj"));
supportingFiles.add(new SupportingFile("nuspec.mustache", packageFolder, packageName + ".nuspec"));
if(Boolean.FALSE.equals(excludeTests)) {
// NOTE: This exists here rather than previous excludeTests block because the test project is considered an optional project file.
@ -494,6 +521,10 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
return "Empty";
}
// for symbol, e.g. $, #
if (getSymbolName(value) != null) {
return camelize(getSymbolName(value));
@ -547,6 +578,14 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen {
this.generatePropertyChanged = generatePropertyChanged;
}
public boolean isNonPublicApi() {
return nonPublicApi;
}
public void setNonPublicApi(final boolean nonPublicApi) {
this.nonPublicApi = nonPublicApi;
}
@Override
public String toModelDocFilename(String name) {
return toModelFilename(name);

View File

@ -62,7 +62,7 @@ public class CppRestClientCodegen extends DefaultCodegen implements CodegenConfi
apiTemplateFiles.put("api-header.mustache", ".h");
apiTemplateFiles.put("api-source.mustache", ".cpp");
templateDir = "cpprest";
embeddedTemplateDir = templateDir = "cpprest";
cliOptions.clear();

View File

@ -10,6 +10,8 @@ import io.swagger.models.properties.MapProperty;
import io.swagger.models.properties.Property;
import io.swagger.codegen.CliOption;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.Arrays;
import java.util.HashMap;
@ -170,7 +172,10 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@ -230,11 +235,26 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
@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)) {
throw new RuntimeException(name + " (reserved word) cannot be used as a model name");
LOGGER.warn(name + " (reserved word) cannot be used as model name. Renamed to " + camelize("model_" + name));
name = "model_" + name; // e.g. return => ModelReturn (after camelize)
}
// 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
@ -281,12 +301,18 @@ public class CsharpDotNet2ClientCodegen extends DefaultCodegen implements Codege
@Override
public String toOperationId(String operationId) {
// method name cannot use reserved keyword, e.g. return
if (isReservedWord(operationId)) {
throw new RuntimeException(operationId + " (reserved word) cannot be used as method name");
// 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");
}
return camelize(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(sanitizeName(operationId));
}
@Override

View File

@ -174,7 +174,10 @@ public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}

View File

@ -0,0 +1,388 @@
package io.swagger.codegen.languages;
import com.samskivert.mustache.Mustache;
import com.samskivert.mustache.Template;
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.IOException;
import java.io.Writer;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class ElixirClientCodegen extends DefaultCodegen implements CodegenConfig {
// source folder where to write the files
protected String sourceFolder = "lib";
protected String apiVersion = "1.0.0";
String supportedElixirVersion = "1.4";
List<String> extraApplications = Arrays.asList(":logger");
List<String> deps = Arrays.asList(
"{:tesla, \"~> 0.5.0\"}",
"{:poison, \">= 1.0.0\"}"
);
public ElixirClientCodegen() {
super();
// set the output folder here
outputFolder = "generated-code/elixir";
/**
* 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
".ex"); // 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
".ex"); // 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.
*/
templateDir = "elixir";
/**
* Reserved words. Override this with reserved words specific to your language
*/
reservedWords = new HashSet<String>(
Arrays.asList(
"sample1", // replace with static values
"sample2")
);
/**
* 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.md.mustache", // the input template or file
"", // the destination folder, relative `outputFolder`
"README.md") // the output file
);
supportingFiles.add(new SupportingFile("config.exs.mustache",
"config",
"config.exs")
);
supportingFiles.add(new SupportingFile("mix.exs.mustache",
"",
"mix.exs")
);
supportingFiles.add(new SupportingFile("test_helper.exs.mustache",
"test",
"test_helper.exs")
);
/**
* Language Specific Primitives. These types will not trigger imports by
* the client generator
*/
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"Type1", // replace these with your types
"Type2")
);
}
/**
* Configures the type of generator.
*
* @return the CodegenType for this generator
* @see io.swagger.codegen.CodegenType
*/
public CodegenType getTag() {
return CodegenType.CLIENT;
}
/**
* 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 "elixir";
}
/**
* 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 an elixir client library (alpha).";
}
@Override
public void processOpts() {
super.processOpts();
additionalProperties.put("supportedElixirVersion", supportedElixirVersion);
additionalProperties.put("extraApplications", join(",", extraApplications));
additionalProperties.put("deps", deps);
additionalProperties.put("underscored", new Mustache.Lambda() {
@Override
public void execute(Template.Fragment fragment, Writer writer) throws IOException {
writer.write(underscored(fragment.execute()));
}
});
additionalProperties.put("modulized", new Mustache.Lambda() {
@Override
public void execute(Template.Fragment fragment, Writer writer) throws IOException {
writer.write(modulized(fragment.execute()));
}
});
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) super.postProcessOperations(objs).get("operations");
List<CodegenOperation> os = (List<CodegenOperation>) operations.get("operation");
List<ExtendedCodegenOperation> newOs = new ArrayList<ExtendedCodegenOperation>();
Pattern pattern = Pattern.compile("(.*)\\{([^\\}]+)\\}(.*)");
for (CodegenOperation o : os) {
ArrayList<String> pathTemplateNames = new ArrayList<String>();
Matcher matcher = pattern.matcher(o.path);
StringBuffer buffer = new StringBuffer();
while (matcher.find()) {
String pathTemplateName = matcher.group(2);
matcher.appendReplacement(buffer, "$1" + "#{" + underscore(pathTemplateName) + "}" + "$3");
pathTemplateNames.add(pathTemplateName);
}
ExtendedCodegenOperation eco = new ExtendedCodegenOperation(o);
if (buffer.toString().isEmpty()) {
eco.setReplacedPathName(o.path);
} else {
eco.setReplacedPathName(buffer.toString());
}
eco.setPathTemplateNames(pathTemplateNames);
newOs.add(eco);
}
operations.put("operation", newOs);
return objs;
}
// We should use String.join if we can use Java8
String join(CharSequence charSequence, Iterable<String> iterable) {
StringBuilder buf = new StringBuilder();
for (String str : iterable) {
if (0 < buf.length()) {
buf.append((charSequence));
}
buf.append(str);
}
return buf.toString();
}
String underscored(String words) {
ArrayList<String> underscoredWords = new ArrayList<String>();
for (String word : words.split(" ")) {
underscoredWords.add(underscore(word));
}
return join("_", underscoredWords);
}
String modulized(String words) {
ArrayList<String> modulizedWords = new ArrayList<String>();
for (String word : words.split(" ")) {
modulizedWords.add(camelize(word));
}
return join("", modulizedWords);
}
/**
* 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; // add an underscore to the name
}
/**
* Location to write model files. You can use the modelPackage() as defined when the class is
* instantiated
*/
public String modelFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + underscored((String) additionalProperties.get("appName")) + "/" + "model";
}
/**
* Location to write api files. You can use the apiPackage() as defined when the class is
* instantiated
*/
@Override
public String apiFileFolder() {
return outputFolder + "/" + sourceFolder + "/" + underscored((String) additionalProperties.get("appName")) + "/" + "api";
}
@Override
public String toApiName(String name) {
if (name.length() == 0) {
return "Default";
}
return initialCaps(name);
}
@Override
public String toApiFilename(String name) {
return snakeCase(name);
}
@Override
public String toModelFilename(String name) {
return snakeCase(name);
}
/**
* 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 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);
}
/**
* 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);
}
class ExtendedCodegenOperation extends CodegenOperation {
private List<String> pathTemplateNames = new ArrayList<String>();
private String replacedPathName;
public ExtendedCodegenOperation(CodegenOperation o) {
super();
// Copy all fields of CodegenOperation
this.responseHeaders.addAll(o.responseHeaders);
this.hasAuthMethods = o.hasAuthMethods;
this.hasConsumes = o.hasConsumes;
this.hasProduces = o.hasProduces;
this.hasParams = o.hasParams;
this.hasOptionalParams = o.hasOptionalParams;
this.returnTypeIsPrimitive = o.returnTypeIsPrimitive;
this.returnSimpleType = o.returnSimpleType;
this.subresourceOperation = o.subresourceOperation;
this.isMapContainer = o.isMapContainer;
this.isListContainer = o.isListContainer;
this.isMultipart = o.isMultipart;
this.hasMore = o.hasMore;
this.isResponseBinary = o.isResponseBinary;
this.hasReference = o.hasReference;
this.isRestfulIndex = o.isRestfulIndex;
this.isRestfulShow = o.isRestfulShow;
this.isRestfulCreate = o.isRestfulCreate;
this.isRestfulUpdate = o.isRestfulUpdate;
this.isRestfulDestroy = o.isRestfulDestroy;
this.isRestful = o.isRestful;
this.path = o.path;
this.operationId = o.operationId;
this.returnType = o.returnType;
this.httpMethod = o.httpMethod;
this.returnBaseType = o.returnBaseType;
this.returnContainer = o.returnContainer;
this.summary = o.summary;
this.unescapedNotes = o.unescapedNotes;
this.notes = o.notes;
this.baseName = o.baseName;
this.defaultResponse = o.defaultResponse;
this.discriminator = o.discriminator;
this.consumes = o.consumes;
this.produces = o.produces;
this.bodyParam = o.bodyParam;
this.allParams = o.allParams;
this.bodyParams = o.bodyParams;
this.pathParams = o.pathParams;
this.queryParams = o.queryParams;
this.headerParams = o.headerParams;
this.formParams = o.formParams;
this.authMethods = o.authMethods;
this.tags = o.tags;
this.responses = o.responses;
this.imports = o.imports;
this.examples = o.examples;
this.externalDocs = o.externalDocs;
this.vendorExtensions = o.vendorExtensions;
this.nickname = o.nickname;
this.operationIdLowerCase = o.operationIdLowerCase;
}
public List<String> getPathTemplateNames() {
return pathTemplateNames;
}
public void setPathTemplateNames(List<String> pathTemplateNames) {
this.pathTemplateNames = pathTemplateNames;
}
public String getReplacedPathName() {
return replacedPathName;
}
public void setReplacedPathName(String replacedPathName) {
this.replacedPathName = replacedPathName;
}
}
@Override
public String escapeQuotationMark(String input) {
return input.replace("\"", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
// no need to escape as Elixir does not support multi-line comments
return input;
}
}

View File

@ -182,8 +182,11 @@ public class ErlangServerCodegen extends DefaultCodegen implements CodegenConfig
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return name + "_"; // add an underscore to the name
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
/**

View File

@ -0,0 +1,320 @@
package io.swagger.codegen.languages;
import com.google.common.base.Strings;
import io.swagger.codegen.*;
import io.swagger.models.Model;
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.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
public class FinchServerCodegen extends DefaultCodegen implements CodegenConfig {
protected String invokerPackage = "io.swagger.petstore.client";
protected String groupId = "io.swagger";
protected String artifactId = "finch-server";
protected String artifactVersion = "1.0.0";
protected String sourceFolder = "src/main/scala";
protected String packageName = "io.swagger.petstore";
public FinchServerCodegen() {
super();
outputFolder = "generated-code/finch";
modelTemplateFiles.put("model.mustache", ".scala");
apiTemplateFiles.put("api.mustache", ".scala");
embeddedTemplateDir = templateDir = "finch";
apiPackage = packageName + ".apis";
modelPackage = packageName + ".models";
setReservedWordsLowerCase(
Arrays.asList(
// Scala
"abstract", "case", "catch", "class", "def",
"do", "else", "extends", "false", "final",
"finally", "for", "forSome", "if", "implicit",
"import", "lazy", "match", "new", "null",
"object", "override", "package", "private", "protected",
"return", "sealed", "super", "this", "throw",
"trait", "try", "true", "type", "val",
"var", "while", "with", "yield",
// Scala-interop languages keywords
"abstract", "continue", "switch", "assert",
"default", "synchronized", "goto",
"break", "double", "implements", "byte",
"public", "throws", "enum", "instanceof", "transient",
"int", "short", "char", "interface", "static",
"void", "finally", "long", "strictfp", "volatile", "const", "float",
"native")
);
defaultIncludes = new HashSet<String>(
Arrays.asList("double",
"Int",
"Long",
"Float",
"Double",
"char",
"float",
"String",
"boolean",
"Boolean",
"Double",
"Integer",
"Long",
"Float",
"List",
"Set",
"Map")
);
typeMapping = new HashMap<String, String>();
typeMapping.put("string", "String");
typeMapping.put("boolean", "Boolean");
typeMapping.put("integer", "Int");
typeMapping.put("float", "Float");
typeMapping.put("long", "Long");
typeMapping.put("double", "Double");
typeMapping.put("number", "BigDecimal");
typeMapping.put("date-time", "LocalDateTime");
typeMapping.put("date", "LocalDateTime");
typeMapping.put("file", "File");
typeMapping.put("array", "Seq");
typeMapping.put("list", "List");
typeMapping.put("map", "Map");
typeMapping.put("object", "Object");
typeMapping.put("binary", "Array[Byte]");
typeMapping.put("Date", "LocalDateTime");
typeMapping.put("DateTime", "LocalDateTime");
additionalProperties.put("modelPackage", modelPackage());
additionalProperties.put("apiPackage", apiPackage());
additionalProperties.put("appName", "Swagger Sample");
additionalProperties.put("appDescription", "A sample swagger server");
additionalProperties.put("infoUrl", "http://swagger.io");
additionalProperties.put("infoEmail", "apiteam@swagger.io");
additionalProperties.put("licenseInfo", "Apache 2.0");
additionalProperties.put("licenseUrl", "http://apache.org/licenses/LICENSE-2.0.html");
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, artifactVersion);
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) {
setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME));
} else {
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
}
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
supportingFiles.add(new SupportingFile("build.sbt", "", "build.sbt"));
supportingFiles.add(new SupportingFile("Server.mustache", sourceFolder, "Server.scala"));
supportingFiles.add(new SupportingFile("DataAccessor.mustache", sourceFolder, "DataAccessor.scala"));
supportingFiles.add(new SupportingFile("project/build.properties", "project", "build.properties"));
supportingFiles.add(new SupportingFile("project/plugins.sbt", "project", "plugins.sbt"));
supportingFiles.add(new SupportingFile("sbt", "", "sbt"));
supportingFiles.add(new SupportingFile("endpoint.mustache", sourceFolder, "endpoint.scala"));
supportingFiles.add(new SupportingFile("errors.mustache", sourceFolder, "errors.scala"));
languageSpecificPrimitives = new HashSet<String>(
Arrays.asList(
"String",
"Boolean",
"Double",
"Int",
"Integer",
"Long",
"Float",
"Any",
"AnyVal",
"AnyRef",
"Object")
);
instantiationTypes.put("array", "ArrayList");
instantiationTypes.put("map", "HashMap");
importMapping = new HashMap<String, String>();
importMapping.put("BigDecimal", "java.math.BigDecimal");
importMapping.put("UUID", "java.util.UUID");
importMapping.put("File", "java.io.File");
importMapping.put("Date", "java.util.Date");
importMapping.put("Timestamp", "java.sql.Timestamp");
importMapping.put("Map", "scala.collection.immutable.Map");
importMapping.put("HashMap", "scala.collection.immutable.HashMap");
importMapping.put("Seq", "scala.collection.immutable.Seq");
importMapping.put("ArrayBuffer", "scala.collection.mutable.ArrayBuffer");
importMapping.put("DateTime", "java.time.LocalDateTime");
importMapping.put("LocalDateTime", "java.time.LocalDateTime");
importMapping.put("LocalDate", "java.time.LocalDate");
importMapping.put("LocalTime", "java.time.LocalTime");
cliOptions.clear();
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "Finch package name (e.g. io.swagger.petstore).")
.defaultValue(this.packageName));
cliOptions.add(new CliOption(CodegenConstants.MODEL_PACKAGE, CodegenConstants.MODEL_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.API_PACKAGE, CodegenConstants.API_PACKAGE_DESC));
}
@Override
public CodegenType getTag() {
return CodegenType.SERVER;
}
@Override
public String getName() {
return "finch";
}
@Override
public String getHelp() {
return "Generates a Scala server application with Finch.";
}
@Override
public String escapeReservedWord(String name) {
return "_" + name;
}
@Override
public String apiFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar);
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar);
}
/**
* Convert Swagger Model object to Codegen Model object
*
* @param name the name of the model
* @param model Swagger Model object
* @param allDefinitions a map of all Swagger models from the spec
* @return Codegen Model object
*/
@Override
public CodegenModel fromModel(String name, Model model, Map<String, Model> allDefinitions) {
CodegenModel codegenModel = super.fromModel(name, model, allDefinitions);
return codegenModel;
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
for (CodegenOperation op : operationList) {
op.httpMethod = op.httpMethod.toLowerCase();
String path = new String(op.path);
// remove first /
if (path.startsWith("/")) {
path = path.substring(1);
}
// remove last /
if (path.endsWith("/")) {
path = path.substring(0, path.length()-1);
}
String[] items = path.split("/", -1);
String scalaPath = "";
int pathParamIndex = 0;
for (int i = 0; i < items.length; ++i) {
if (items[i].matches("^\\{(.*)\\}$")) { // wrap in {}
// find the datatype of the parameter
final CodegenParameter cp = op.pathParams.get(pathParamIndex);
// TODO: Handle non-primitives
scalaPath = scalaPath + cp.dataType.toLowerCase();
pathParamIndex++;
} else {
scalaPath = scalaPath + "\"" + items[i] + "\"";
}
if (i != items.length -1) {
scalaPath = scalaPath + " :: ";
}
}
for (CodegenParameter p : op.allParams) {
// TODO: This hacky, should be converted to mappings if possible to keep it clean.
// This could also be done using template imports
if(Boolean.TRUE.equals(p.isPrimitiveType)) {
p.vendorExtensions.put("x-codegen-normalized-path-type", p.dataType.toLowerCase());
p.vendorExtensions.put("x-codegen-normalized-input-type", p.dataType);
} else if(Boolean.TRUE.equals(p.isBodyParam)) {
p.vendorExtensions.put("x-codegen-normalized-path-type", "jsonBody["+ p.dataType + "]");
p.vendorExtensions.put("x-codegen-normalized-input-type", p.dataType);
} else if(Boolean.TRUE.equals(p.isContainer) || Boolean.TRUE.equals(p.isListContainer)) {
p.vendorExtensions.put("x-codegen-normalized-path-type", "params(\""+ p.paramName + "\")");
p.vendorExtensions.put("x-codegen-normalized-input-type", p.dataType.replaceAll("^[^\\[]+", "Seq"));
} else if(Boolean.TRUE.equals(p.isFile)) {
p.vendorExtensions.put("x-codegen-normalized-path-type", "fileUpload(\""+ p.paramName + "\")");
p.vendorExtensions.put("x-codegen-normalized-input-type", "FileUpload");
} else {
p.vendorExtensions.put("x-codegen-normalized-path-type", p.dataType);
p.vendorExtensions.put("x-codegen-normalized-input-type", p.dataType);
}
}
op.vendorExtensions.put("x-codegen-path", scalaPath);
}
return objs;
}
@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)) {
type = typeMapping.get(swaggerType);
if (languageSpecificPrimitives.contains(type)) {
return toModelName(type);
}
} else {
type = swaggerType;
}
return toModelName(type);
}
@Override
public String escapeQuotationMark(String input) {
// remove " to avoid code injection
return input.replace("\"", "");
}
@Override
public String escapeUnsafeCharacters(String input) {
return input.replace("*/", "*_/").replace("/*", "/_*");
}
public void setPackageName(String packageName) {
this.packageName = packageName;
}
}

View File

@ -177,8 +177,11 @@ public class FlashClientCodegen extends DefaultCodegen implements CodegenConfig
}
@Override
public String escapeReservedWord(String name) {
return name + "_";
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@Override

View File

@ -236,10 +236,13 @@ public class FlaskConnexionCodegen extends DefaultCodegen implements CodegenConf
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name; // add an underscore to the name
}
/**
* Location to write api files. You can use the apiPackage() as defined when the class is
* instantiated

View File

@ -43,7 +43,7 @@ public class GoClientCodegen extends DefaultCodegen implements CodegenConfig {
modelDocTemplateFiles.put("model_doc.mustache", ".md");
apiDocTemplateFiles.put("api_doc.mustache", ".md");
templateDir = "go";
embeddedTemplateDir = templateDir = "go";
setReservedWordsLowerCase(
Arrays.asList(
@ -180,9 +180,10 @@ public class GoClientCodegen extends DefaultCodegen implements CodegenConfig {
// - XName
// - X_Name
// ... or maybe a suffix?
// - Name_ ... think this will work.
// FIXME: This should also really be a customizable option
// - Name_ ... think this will work.
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return camelize(name) + '_';
}

View File

@ -204,6 +204,9 @@ public class GoServerCodegen extends DefaultCodegen implements CodegenConfig {
*/
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name; // add an underscore to the name
}

View File

@ -154,8 +154,11 @@ public class HaskellServantCodegen extends DefaultCodegen implements CodegenConf
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return name + "_";
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
public String firstLetterToUpper(String word) {

View File

@ -68,7 +68,7 @@ public class JMeterCodegen extends DefaultCodegen implements CodegenConfig {
* 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.
*/
templateDir = "JMeter";
embeddedTemplateDir = templateDir = "JMeter";
/*
* Api Package. Optional, if needed, this can be used in templates
@ -119,10 +119,13 @@ public class JMeterCodegen extends DefaultCodegen implements CodegenConfig {
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
}
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
/**
* Location to write model files. You can use the modelPackage() as defined when the class is

View File

@ -27,8 +27,6 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
protected boolean addConsumesProducesJson = true;
protected boolean useJaxbAnnotations = true;
protected boolean useBeanValidation = false;
protected boolean generateSpringApplication = false;
@ -41,7 +39,7 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
protected boolean useWadlFeature = false;
protected boolean useMultipartFeature = false;
protected boolean useBeanValidationFeature = false;
protected boolean generateSpringBootApplication= false;
@ -56,6 +54,10 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
protected boolean useLoggingFeatureForTests = false;
protected boolean useAnnotatedBasePath = false;
protected boolean generateNonSpringApplication = false;
public JavaCXFServerCodegen()
{
super();
@ -84,7 +86,6 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
cliOptions.add(CliOption.newBoolean(USE_JAXB_ANNOTATIONS, "Use JAXB annotations for XML"));
cliOptions.add(CliOption.newBoolean(USE_BEANVALIDATION, "Use BeanValidation API annotations"));
cliOptions.add(CliOption.newBoolean(GENERATE_SPRING_APPLICATION, "Generate Spring application"));
cliOptions.add(CliOption.newBoolean(USE_SPRING_ANNOTATION_CONFIG, "Use Spring Annotation Config"));
@ -108,6 +109,9 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
cliOptions
.add(CliOption.newBoolean(ADD_CONSUMES_PRODUCES_JSON, "Add @Consumes/@Produces Json to API interface"));
cliOptions.add(CliOption.newBoolean(USE_ANNOTATED_BASE_PATH, "Use @Path annotations for basePath"));
cliOptions.add(CliOption.newBoolean(GENERATE_NON_SPRING_APPLICATION, "Generate non-Spring application"));
}
@ -121,11 +125,6 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
this.setUseJaxbAnnotations(useJaxbAnnotationsProp);
}
if (additionalProperties.containsKey(USE_BEANVALIDATION)) {
boolean useBeanValidationProp = convertPropertyToBooleanAndWriteBack(USE_BEANVALIDATION);
this.setUseBeanValidation(useBeanValidationProp);
}
if (additionalProperties.containsKey(ADD_CONSUMES_PRODUCES_JSON)) {
this.setAddConsumesProducesJson(convertPropertyToBooleanAndWriteBack(ADD_CONSUMES_PRODUCES_JSON));
}
@ -159,6 +158,16 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
this.setGenerateJbossDeploymentDescriptor(generateJbossDeploymentDescriptorProp);
}
if (additionalProperties.containsKey(USE_ANNOTATED_BASE_PATH)) {
boolean useAnnotatedBasePathProp = convertPropertyToBooleanAndWriteBack(USE_ANNOTATED_BASE_PATH);
this.setUseAnnotatedBasePath(useAnnotatedBasePathProp);
}
if (additionalProperties.containsKey(GENERATE_NON_SPRING_APPLICATION)) {
boolean generateNonSpringApplication = convertPropertyToBooleanAndWriteBack(GENERATE_NON_SPRING_APPLICATION);
this.setGenerateNonSpringApplication(generateNonSpringApplication);
}
supportingFiles.clear(); // Don't need extra files provided by AbstractJAX-RS & Java Codegen
writeOptional(outputFolder, new SupportingFile("server/pom.mustache", "", "pom.xml"));
@ -191,10 +200,12 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
(testResourcesFolder + '/'), "application.properties"));
}
}
if (this.generateNonSpringApplication) {
writeOptional(outputFolder, new SupportingFile("server/nonspring-web.mustache",
("src/main/webapp/WEB-INF"), "web.xml"));
}
}
@Override
@ -224,10 +235,6 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
return "Generates a Java JAXRS Server application based on Apache CXF framework.";
}
public void setUseBeanValidation(boolean useBeanValidation) {
this.useBeanValidation = useBeanValidation;
}
public void setGenerateSpringApplication(boolean generateSpringApplication) {
this.generateSpringApplication = generateSpringApplication;
}
@ -293,4 +300,12 @@ public class JavaCXFServerCodegen extends AbstractJavaJAXRSServerCodegen
this.addConsumesProducesJson = addConsumesProducesJson;
}
public void setUseAnnotatedBasePath(boolean useAnnotatedBasePath) {
this.useAnnotatedBasePath = useAnnotatedBasePath;
}
public void setGenerateNonSpringApplication(boolean generateNonSpringApplication) {
this.generateNonSpringApplication = generateNonSpringApplication;
}
}

View File

@ -1,8 +1,10 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.CliOption;
import io.swagger.codegen.CodegenModel;
import io.swagger.codegen.CodegenProperty;
import io.swagger.codegen.SupportingFile;
import io.swagger.codegen.languages.features.BeanValidationFeatures;
import java.io.File;
@ -13,7 +15,10 @@ import java.io.File;
* in /src/gen/java and a sample ServiceImpl in /src/main/java. The API uses CDI
* to get an instance of ServiceImpl that implements the Service interface.
*/
public class JavaJAXRSCXFCDIServerCodegen extends JavaJAXRSSpecServerCodegen {
public class JavaJAXRSCXFCDIServerCodegen extends JavaJAXRSSpecServerCodegen implements BeanValidationFeatures {
protected boolean useBeanValidation = true;
/**
* Default constructor
*/
@ -32,6 +37,8 @@ public class JavaJAXRSCXFCDIServerCodegen extends JavaJAXRSSpecServerCodegen {
// Updated template directory
embeddedTemplateDir = templateDir = JAXRS_TEMPLATE_DIRECTORY_NAME
+ File.separator + "cxf-cdi";
cliOptions.add(CliOption.newBoolean(USE_BEANVALIDATION, "Use BeanValidation API annotations"));
}
@Override
@ -43,6 +50,14 @@ public class JavaJAXRSCXFCDIServerCodegen extends JavaJAXRSSpecServerCodegen {
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(USE_BEANVALIDATION)) {
this.setUseBeanValidation(convertPropertyToBoolean(USE_BEANVALIDATION));
}
if (useBeanValidation) {
writePropertyBack(USE_BEANVALIDATION, useBeanValidation);
}
supportingFiles.clear(); // Don't need extra files provided by AbstractJAX-RS & Java Codegen
// writeOptional means these files are only written if they don't already exist
@ -73,4 +88,7 @@ public class JavaJAXRSCXFCDIServerCodegen extends JavaJAXRSSpecServerCodegen {
+ "Apache CXF runtime and a Java EE runtime with CDI enabled.";
}
public void setUseBeanValidation(boolean useBeanValidation) {
this.useBeanValidation = useBeanValidation;
}
}

View File

@ -2,27 +2,30 @@ package io.swagger.codegen.languages;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
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.codegen.SupportingFile;
import io.swagger.codegen.languages.features.BeanValidationFeatures;
import io.swagger.models.Operation;
import io.swagger.models.Swagger;
import io.swagger.models.properties.Property;
import io.swagger.util.Json;
import org.apache.commons.io.FileUtils;
public class JavaJAXRSSpecServerCodegen extends AbstractJavaJAXRSServerCodegen
{
public JavaJAXRSSpecServerCodegen()
{
public class JavaJAXRSSpecServerCodegen extends AbstractJavaJAXRSServerCodegen
{
public JavaJAXRSSpecServerCodegen()
{
super();
invokerPackage = "io.swagger.api";
artifactId = "swagger-jaxrs-server";
@ -67,26 +70,27 @@ public class JavaJAXRSSpecServerCodegen extends AbstractJavaJAXRSServerCodegen
library.setEnum(supportedLibraries);
cliOptions.add(library);
}
@Override
public void processOpts()
{
super.processOpts();
supportingFiles.clear(); // Don't need extra files provided by AbstractJAX-RS & Java Codegen
}
@Override
public void processOpts()
{
super.processOpts();
supportingFiles.clear(); // Don't need extra files provided by AbstractJAX-RS & Java Codegen
writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml"));
writeOptional(outputFolder, new SupportingFile("RestApplication.mustache",
(sourceFolder + '/' + invokerPackage).replace(".", "/"), "RestApplication.java"));
}
}
@Override
public String getName()
{
return "jaxrs-spec";
}
@Override
public String getName()
{
return "jaxrs-spec";
}
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
@ -127,16 +131,16 @@ public class JavaJAXRSSpecServerCodegen extends AbstractJavaJAXRSServerCodegen
model.imports.remove("JsonProperty");
}
@Override
@Override
public void preprocessSwagger(Swagger swagger) {
//copy input swagger to output folder
try {
String swaggerJson = Json.pretty(swagger);
//copy input swagger to output folder
try {
String swaggerJson = Json.pretty(swagger);
FileUtils.writeStringToFile(new File(outputFolder + File.separator + "swagger.json"), swaggerJson);
} catch (IOException e) {
} catch (IOException e) {
throw new RuntimeException(e.getMessage(), e.getCause());
}
super.preprocessSwagger(swagger);
}
super.preprocessSwagger(swagger);
}
@Override

View File

@ -1,6 +1,7 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.codegen.languages.features.BeanValidationFeatures;
import io.swagger.models.Operation;
import java.util.*;
@ -12,7 +13,7 @@ public class JavaJerseyServerCodegen extends AbstractJavaJAXRSServerCodegen {
protected static final String LIBRARY_JERSEY1 = "jersey1";
protected static final String LIBRARY_JERSEY2 = "jersey2";
/**
* Default library template to use. (Default:{@value #DEFAULT_LIBRARY})
*/
@ -84,7 +85,7 @@ public class JavaJerseyServerCodegen extends AbstractJavaJAXRSServerCodegen {
if (StringUtils.isEmpty(library)) {
setLibrary(DEFAULT_LIBRARY);
}
if ( additionalProperties.containsKey(CodegenConstants.IMPL_FOLDER)) {
implFolder = (String) additionalProperties.get(CodegenConstants.IMPL_FOLDER);
}
@ -160,5 +161,5 @@ public class JavaJerseyServerCodegen extends AbstractJavaJAXRSServerCodegen {
opList.add(co);
co.baseName = basePath;
}
}

View File

@ -1,6 +1,7 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.codegen.languages.features.BeanValidationFeatures;
import io.swagger.codegen.languages.features.JbossFeature;
import io.swagger.models.Operation;
import org.apache.commons.lang3.BooleanUtils;
@ -12,7 +13,7 @@ import java.util.*;
public class JavaResteasyServerCodegen extends AbstractJavaJAXRSServerCodegen implements JbossFeature {
protected boolean generateJbossDeploymentDescriptor = true;
public JavaResteasyServerCodegen() {
super();
@ -58,7 +59,7 @@ public class JavaResteasyServerCodegen extends AbstractJavaJAXRSServerCodegen im
GENERATE_JBOSS_DEPLOYMENT_DESCRIPTOR);
this.setGenerateJbossDeploymentDescriptor(generateJbossDeploymentDescriptorProp);
}
writeOptional(outputFolder, new SupportingFile("pom.mustache", "", "pom.xml"));
writeOptional(outputFolder, new SupportingFile("gradle.mustache", "", "build.gradle"));
writeOptional(outputFolder, new SupportingFile("settingsGradle.mustache", "", "settings.gradle"));
@ -214,7 +215,7 @@ public class JavaResteasyServerCodegen extends AbstractJavaJAXRSServerCodegen im
return objs;
}
public void setGenerateJbossDeploymentDescriptor(boolean generateJbossDeploymentDescriptor) {
this.generateJbossDeploymentDescriptor = generateJbossDeploymentDescriptor;
}

View File

@ -84,7 +84,7 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
modelTestTemplateFiles.put("model_test.mustache", ".js");
apiTemplateFiles.put("api.mustache", ".js");
apiTestTemplateFiles.put("api_test.mustache", ".js");
templateDir = "Javascript";
embeddedTemplateDir = templateDir = "Javascript";
apiPackage = "api";
modelPackage = "model";
modelDocTemplateFiles.put("model_doc.mustache", ".md");
@ -313,7 +313,10 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@ -1021,6 +1024,10 @@ public class JavascriptClientCodegen extends DefaultCodegen implements CodegenCo
@Override
public String toEnumVarName(String value, String datatype) {
if (value.length() == 0) {
return "empty";
}
// for symbol, e.g. $, #
if (getSymbolName(value) != null) {
return (getSymbolName(value)).toUpperCase();

View File

@ -102,7 +102,10 @@ public class JavascriptClosureAngularClientCodegen extends DefaultCodegen implem
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}

View File

@ -1,20 +1,7 @@
package io.swagger.codegen.languages;
import static com.google.common.base.Strings.isNullOrEmpty;
import static io.swagger.codegen.CodegenConstants.OPTIONAL_PROJECT_FILE;
import static io.swagger.codegen.CodegenConstants.OPTIONAL_PROJECT_FILE_DESC;
import static io.swagger.codegen.CodegenConstants.PACKAGE_NAME;
import static io.swagger.codegen.CodegenConstants.PACKAGE_VERSION;
import static io.swagger.codegen.CodegenConstants.RETURN_ICOLLECTION;
import static io.swagger.codegen.CodegenConstants.RETURN_ICOLLECTION_DESC;
import static io.swagger.codegen.CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG;
import static io.swagger.codegen.CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC;
import static io.swagger.codegen.CodegenConstants.SOURCE_FOLDER;
import static io.swagger.codegen.CodegenConstants.SOURCE_FOLDER_DESC;
import static io.swagger.codegen.CodegenConstants.USE_COLLECTION;
import static io.swagger.codegen.CodegenConstants.USE_COLLECTION_DESC;
import static io.swagger.codegen.CodegenConstants.USE_DATETIME_OFFSET;
import static io.swagger.codegen.CodegenConstants.USE_DATETIME_OFFSET_DESC;
import static io.swagger.codegen.CodegenConstants.*;
import static io.swagger.codegen.CodegenType.SERVER;
import static java.util.Arrays.asList;
import static java.util.UUID.randomUUID;
@ -71,6 +58,9 @@ public class NancyFXServerCodegen extends AbstractCSharpCodegen {
outputFolder = "generated-code" + File.separator + getName();
apiTemplateFiles.put("api.mustache", ".cs");
// Early versions use no prefix for interfaces. Defaulting to I- common practice would break existing users.
setInterfacePrefix("");
// contextually reserved words
setReservedWordsLowerCase(
asList("var", "async", "await", "dynamic", "yield")
@ -82,6 +72,7 @@ public class NancyFXServerCodegen extends AbstractCSharpCodegen {
addOption(PACKAGE_NAME, "C# package name (convention: Title.Case).", packageName);
addOption(PACKAGE_VERSION, "C# package version.", packageVersion);
addOption(SOURCE_FOLDER, SOURCE_FOLDER_DESC, sourceFolder);
addOption(INTERFACE_PREFIX, INTERFACE_PREFIX_DESC, interfacePrefix);
// CLI Switches
addSwitch(SORT_PARAMS_BY_REQUIRED_FLAG, SORT_PARAMS_BY_REQUIRED_FLAG_DESC, sortParamsByRequiredFlag);
@ -292,6 +283,10 @@ public class NancyFXServerCodegen extends AbstractCSharpCodegen {
@Override
public String toEnumVarName(final String name, final String datatype) {
if (name.length() == 0) {
return "Empty";
}
final String enumName = camelize(
sanitizeName(name)
.replaceFirst("^_", "")

View File

@ -147,13 +147,16 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
/**
* 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
* those terms here. This logic is only called if a variable matches the reserved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
/**
@ -307,7 +310,12 @@ public class NodeJSServerCodegen extends DefaultCodegen implements CodegenConfig
if (info.getTitle() != null) {
// when info.title is defined, use it for projectName
// used in package.json
projectName = dashize(info.getTitle());
projectName = info.getTitle()
.replaceAll("[^a-zA-Z0-9]", "-")
.replaceAll("^[-]*", "")
.replaceAll("[-]*$", "")
.replaceAll("[-]{2,}", "-")
.toLowerCase();
this.additionalProperties.put("projectName", projectName);
}
}

View File

@ -539,8 +539,17 @@ public class ObjcClientCodegen extends DefaultCodegen implements CodegenConfig {
return toVarName(name);
}
/**
* 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 reserved words
*
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}

View File

@ -109,7 +109,8 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue(Boolean.TRUE.toString()));
cliOptions.add(CliOption.newBoolean(CodegenConstants.ENSURE_UNIQUE_PARAMS, CodegenConstants
.ENSURE_UNIQUE_PARAMS_DESC).defaultValue(Boolean.TRUE.toString()));
cliOptions.add(new CliOption(CodegenConstants.HIDE_GENERATION_TIMESTAMP, CodegenConstants.HIDE_GENERATION_TIMESTAMP_DESC)
.defaultValue(Boolean.TRUE.toString()));
}
@ -134,6 +135,14 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
additionalProperties.put("apiDocPath", apiDocPath);
additionalProperties.put("modelDocPath", modelDocPath);
// default HIDE_GENERATION_TIMESTAMP to true
if (!additionalProperties.containsKey(CodegenConstants.HIDE_GENERATION_TIMESTAMP)) {
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP, Boolean.TRUE.toString());
} else {
additionalProperties.put(CodegenConstants.HIDE_GENERATION_TIMESTAMP,
Boolean.valueOf(additionalProperties().get(CodegenConstants.HIDE_GENERATION_TIMESTAMP).toString()));
}
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"));
@ -162,6 +171,9 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@ -396,7 +408,7 @@ public class PerlClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public void setParameterExampleValue(CodegenParameter p) {
if (Boolean.TRUE.equals(p.isString) || Boolean.TRUE.equals(p.isBinary) ||
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)) {

View File

@ -232,17 +232,25 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
if (additionalProperties.containsKey(CodegenConstants.INVOKER_PACKAGE)) {
this.setInvokerPackage((String) additionalProperties.get(CodegenConstants.INVOKER_PACKAGE));
// Update the invokerPackage for the default apiPackage and modelPackage
apiPackage = invokerPackage + "\\" + apiDirName;
modelPackage = invokerPackage + "\\" + modelDirName;
} else {
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
}
if (!additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
if (additionalProperties.containsKey(CodegenConstants.MODEL_PACKAGE)) {
// Update model package to contain the specified model package name and the invoker package
modelPackage = invokerPackage + "\\" + (String) additionalProperties.get(CodegenConstants.MODEL_PACKAGE);
}
additionalProperties.put(CodegenConstants.MODEL_PACKAGE, modelPackage);
if (!additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
if (additionalProperties.containsKey(CodegenConstants.API_PACKAGE)) {
// Update model package to contain the specified model package name and the invoker package
apiPackage = invokerPackage + "\\" + (String) additionalProperties.get(CodegenConstants.API_PACKAGE);
}
additionalProperties.put(CodegenConstants.API_PACKAGE, apiPackage);
if (additionalProperties.containsKey(COMPOSER_PROJECT_NAME)) {
this.setComposerProjectName((String) additionalProperties.get(COMPOSER_PROJECT_NAME));
@ -307,7 +315,10 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@ -480,7 +491,13 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
// add prefix and/or suffic only if name does not start wth \ (e.g. \DateTime)
if (!name.matches("^\\\\.*")) {
name = modelNamePrefix + name + modelNameSuffix;
if (!StringUtils.isEmpty(modelNamePrefix)) {
name = modelNamePrefix + "_" + name;
}
if (!StringUtils.isEmpty(modelNameSuffix)) {
name = name + "_" + modelNameSuffix;
}
}
// camelize the model name
@ -644,6 +661,10 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "EMPTY";
}
// number
if ("int".equals(datatype) || "double".equals(datatype) || "float".equals(datatype)) {
String varName = name;

View File

@ -251,7 +251,10 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}

View File

@ -198,8 +198,11 @@ public class Qt5CPPGenerator extends DefaultCodegen implements CodegenConfig {
* @return the escaped term
*/
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
/**

View File

@ -186,7 +186,10 @@ public class Rails5ServerCodegen extends DefaultCodegen implements CodegenConfig
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}

View File

@ -330,7 +330,10 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@ -568,6 +571,10 @@ public class RubyClientCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "EMPTY";
}
// number
if ("Integer".equals(datatype) || "Float".equals(datatype)) {
String varName = name;

View File

@ -65,7 +65,6 @@ public class ScalatraServerCodegen extends AbstractScalaCodegen implements Codeg
// mapped to String as a workaround
typeMapping.put("binary", "String");
additionalProperties.put("appName", "Swagger Sample");
additionalProperties.put("appName", "Swagger Sample");
additionalProperties.put("appDescription", "A sample swagger server");
additionalProperties.put("infoUrl", "http://swagger.io");

View File

@ -107,10 +107,13 @@ public class SilexServerCodegen extends DefaultCodegen implements CodegenConfig
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}
@Override
public String apiFileFolder() {
return (outputFolder + "/" + apiPackage()).replace('/', File.separatorChar);

View File

@ -104,7 +104,10 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}

View File

@ -118,7 +118,10 @@ public class SlimFrameworkServerCodegen extends DefaultCodegen implements Codege
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}

View File

@ -1,6 +1,7 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.codegen.languages.features.BeanValidationFeatures;
import io.swagger.models.Operation;
import io.swagger.models.Path;
import io.swagger.models.Swagger;
@ -8,16 +9,18 @@ import io.swagger.models.Swagger;
import java.io.File;
import java.util.*;
public class SpringCodegen extends AbstractJavaCodegen {
public class SpringCodegen extends AbstractJavaCodegen implements BeanValidationFeatures {
public static final String DEFAULT_LIBRARY = "spring-boot";
public static final String TITLE = "title";
public static final String CONFIG_PACKAGE = "configPackage";
public static final String BASE_PACKAGE = "basePackage";
public static final String INTERFACE_ONLY = "interfaceOnly";
public static final String DELEGATE_PATTERN = "delegatePattern";
public static final String SINGLE_CONTENT_TYPES = "singleContentTypes";
public static final String JAVA_8 = "java8";
public static final String ASYNC = "async";
public static final String RESPONSE_WRAPPER = "responseWrapper";
public static final String USE_TAGS = "useTags";
public static final String SPRING_MVC_LIBRARY = "spring-mvc";
public static final String SPRING_CLOUD_LIBRARY = "spring-cloud";
@ -25,10 +28,13 @@ public class SpringCodegen extends AbstractJavaCodegen {
protected String configPackage = "io.swagger.configuration";
protected String basePackage = "io.swagger";
protected boolean interfaceOnly = false;
protected boolean delegatePattern = false;
protected boolean singleContentTypes = false;
protected boolean java8 = false;
protected boolean async = false;
protected String responseWrapper = "";
protected boolean useTags = false;
protected boolean useBeanValidation = true;
public SpringCodegen() {
super();
@ -50,10 +56,13 @@ public class SpringCodegen extends AbstractJavaCodegen {
cliOptions.add(new CliOption(CONFIG_PACKAGE, "configuration package for generated code"));
cliOptions.add(new CliOption(BASE_PACKAGE, "base package for generated code"));
cliOptions.add(CliOption.newBoolean(INTERFACE_ONLY, "Whether to generate only API interface stubs without the server files."));
cliOptions.add(CliOption.newBoolean(DELEGATE_PATTERN, "Whether to generate the server files using the delegate pattern"));
cliOptions.add(CliOption.newBoolean(SINGLE_CONTENT_TYPES, "Whether to select only one produces/consumes content-type by operation."));
cliOptions.add(CliOption.newBoolean(JAVA_8, "use java8 default interface"));
cliOptions.add(CliOption.newBoolean(ASYNC, "use async Callable controllers"));
cliOptions.add(new CliOption(RESPONSE_WRAPPER, "wrap the responses in given type (Future,Callable,CompletableFuture,ListenableFuture,DeferredResult,HystrixCommand,RxObservable,RxSingle or fully qualified type)"));
cliOptions.add(CliOption.newBoolean(USE_TAGS, "use tags for creating interface and controller classnames"));
cliOptions.add(CliOption.newBoolean(USE_BEANVALIDATION, "Use BeanValidation API annotations"));
supportedLibraries.put(DEFAULT_LIBRARY, "Spring-boot Server application using the SpringFox integration.");
supportedLibraries.put(SPRING_MVC_LIBRARY, "Spring-MVC Server application using the SpringFox integration.");
@ -121,10 +130,18 @@ public class SpringCodegen extends AbstractJavaCodegen {
this.setInterfaceOnly(Boolean.valueOf(additionalProperties.get(INTERFACE_ONLY).toString()));
}
if (additionalProperties.containsKey(DELEGATE_PATTERN)) {
this.setDelegatePattern(Boolean.valueOf(additionalProperties.get(DELEGATE_PATTERN).toString()));
}
if (additionalProperties.containsKey(SINGLE_CONTENT_TYPES)) {
this.setSingleContentTypes(Boolean.valueOf(additionalProperties.get(SINGLE_CONTENT_TYPES).toString()));
}
if (additionalProperties.containsKey(JAVA_8)) {
this.setJava8(Boolean.valueOf(additionalProperties.get(JAVA_8).toString()));
}
if (additionalProperties.containsKey(ASYNC)) {
this.setAsync(Boolean.valueOf(additionalProperties.get(ASYNC).toString()));
}
@ -133,9 +150,26 @@ public class SpringCodegen extends AbstractJavaCodegen {
this.setResponseWrapper((String) additionalProperties.get(RESPONSE_WRAPPER));
}
if (additionalProperties.containsKey(USE_TAGS)) {
this.setUseTags(Boolean.valueOf(additionalProperties.get(USE_TAGS).toString()));
}
if (additionalProperties.containsKey(USE_BEANVALIDATION)) {
this.setUseBeanValidation(convertPropertyToBoolean(USE_BEANVALIDATION));
}
if (useBeanValidation) {
writePropertyBack(USE_BEANVALIDATION, useBeanValidation);
}
supportingFiles.add(new SupportingFile("pom.mustache", "", "pom.xml"));
supportingFiles.add(new SupportingFile("README.mustache", "", "README.md"));
if (this.interfaceOnly && this.delegatePattern) {
throw new IllegalArgumentException(
String.format("Can not generate code with `%s` and `%s` both true.", DELEGATE_PATTERN, INTERFACE_ONLY));
}
if (!this.interfaceOnly) {
if (library.equals(DEFAULT_LIBRARY)) {
supportingFiles.add(new SupportingFile("homeController.mustache",
@ -194,6 +228,16 @@ public class SpringCodegen extends AbstractJavaCodegen {
(sourceFolder + File.separator + configPackage).replace(".", java.io.File.separator), "JacksonConfiguration.java"));
}
}
if (!this.delegatePattern && this.java8) {
additionalProperties.put("jdk8-no-delegate", true);
}
if (this.delegatePattern) {
additionalProperties.put("isDelegate", "true");
apiTemplateFiles.put("apiDelegate.mustache", "Delegate.java");
}
if (this.java8) {
additionalProperties.put("javaVersion", "1.8");
@ -239,7 +283,7 @@ public class SpringCodegen extends AbstractJavaCodegen {
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
if(library.equals(DEFAULT_LIBRARY) || library.equals(SPRING_MVC_LIBRARY)) {
if((library.equals(DEFAULT_LIBRARY) || library.equals(SPRING_MVC_LIBRARY)) && !useTags) {
String basePath = resourcePath;
if (basePath.startsWith("/")) {
basePath = basePath.substring(1);
@ -408,6 +452,8 @@ public class SpringCodegen extends AbstractJavaCodegen {
public void setInterfaceOnly(boolean interfaceOnly) { this.interfaceOnly = interfaceOnly; }
public void setDelegatePattern(boolean delegatePattern) { this.delegatePattern = delegatePattern; }
public void setSingleContentTypes(boolean singleContentTypes) {
this.singleContentTypes = singleContentTypes;
}
@ -418,6 +464,10 @@ public class SpringCodegen extends AbstractJavaCodegen {
public void setResponseWrapper(String responseWrapper) { this.responseWrapper = responseWrapper; }
public void setUseTags(boolean useTags) {
this.useTags = useTags;
}
@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
@ -462,5 +512,9 @@ public class SpringCodegen extends AbstractJavaCodegen {
return objs;
}
public void setUseBeanValidation(boolean useBeanValidation) {
this.useBeanValidation = useBeanValidation;
}
}

View File

@ -77,7 +77,10 @@ public class StaticDocCodegen extends DefaultCodegen implements CodegenConfig {
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}

View File

@ -24,6 +24,8 @@ public class StaticHtml2Generator extends DefaultCodegen implements CodegenConfi
protected String artifactVersion = "1.0.0";
protected String jsProjectName;
protected String jsModuleName;
protected String perlModuleName = "WWW::SwaggerClient";
protected String pythonPackageName = "swagger_client";
public StaticHtml2Generator() {
super();
@ -40,6 +42,8 @@ public class StaticHtml2Generator extends DefaultCodegen implements CodegenConfi
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.PHP_INVOKER_PACKAGE, CodegenConstants.PHP_INVOKER_PACKAGE_DESC));
cliOptions.add(new CliOption(CodegenConstants.PERL_MODULE_NAME, CodegenConstants.PERL_MODULE_NAME_DESC));
cliOptions.add(new CliOption(CodegenConstants.PYTHON_PACKAGE_NAME, CodegenConstants.PYTHON_PACKAGE_NAME_DESC));
cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "C# package name"));
cliOptions.add(new CliOption(CodegenConstants.GROUP_ID, CodegenConstants.GROUP_ID_DESC));
cliOptions.add(new CliOption(CodegenConstants.ARTIFACT_ID, CodegenConstants.ARTIFACT_ID_DESC));
@ -53,6 +57,8 @@ public class StaticHtml2Generator extends DefaultCodegen implements CodegenConfi
additionalProperties.put("licenseUrl", "http://apache.org/licenses/LICENSE-2.0.html");
additionalProperties.put(CodegenConstants.INVOKER_PACKAGE, invokerPackage);
additionalProperties.put(CodegenConstants.PHP_INVOKER_PACKAGE, phpInvokerPackage);
additionalProperties.put(CodegenConstants.PERL_MODULE_NAME, perlModuleName);
additionalProperties.put(CodegenConstants.PYTHON_PACKAGE_NAME, pythonPackageName);
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
additionalProperties.put(CodegenConstants.GROUP_ID, groupId);
additionalProperties.put(CodegenConstants.ARTIFACT_ID, artifactId);

View File

@ -234,10 +234,13 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name; // add an underscore to the name
}
@Override
public String modelFileFolder() {
return outputFolder + File.separator + sourceFolder + modelPackage().replace('.', File.separatorChar);
@ -450,14 +453,7 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
@Override
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions, Swagger swagger) {
path = normalizePath(path); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
List<Parameter> parameters = operation.getParameters();
parameters = Lists.newArrayList(Iterators.filter(parameters.iterator(), new Predicate<Parameter>() {
@Override
public boolean apply(@Nullable Parameter parameter) {
return !(parameter instanceof HeaderParameter);
}
}));
operation.setParameters(parameters);
// issue 3914 - removed logic designed to remove any parameter of type HeaderParameter
return super.fromOperation(path, httpMethod, operation, definitions, swagger);
}
@ -512,6 +508,10 @@ public class Swift3Codegen extends DefaultCodegen implements CodegenConfig {
@Override
public String toEnumVarName(String name, String datatype) {
if (name.length() == 0) {
return "empty";
}
// for symbol, e.g. $, #
if (getSymbolName(name) != null) {
return camelize(WordUtils.capitalizeFully(getSymbolName(name).toUpperCase()), true);

View File

@ -232,11 +232,14 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
protected boolean isReservedWord(String word) {
return word != null && reservedWords.contains(word); //don't lowercase as super does
}
@Override
public String escapeReservedWord(String name) {
return "_" + name; // add an underscore to the name
}
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name; // add an underscore to the name
}
@Override
public String modelFileFolder() {
@ -388,6 +391,10 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
@SuppressWarnings("static-method")
public String toSwiftyEnumName(String value) {
if (value.length() == 0) {
return "Empty";
}
if (value.matches("^-?\\d*\\.{0,1}\\d+.*")) { // starts with number
value = "Number" + value;
value = value.replaceAll("-", "Minus");
@ -481,14 +488,7 @@ public class SwiftCodegen extends DefaultCodegen implements CodegenConfig {
@Override
public CodegenOperation fromOperation(String path, String httpMethod, Operation operation, Map<String, Model> definitions, Swagger swagger) {
path = normalizePath(path); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
List<Parameter> parameters = operation.getParameters();
parameters = Lists.newArrayList(Iterators.filter(parameters.iterator(), new Predicate<Parameter>() {
@Override
public boolean apply(@Nullable Parameter parameter) {
return !(parameter instanceof HeaderParameter);
}
}));
operation.setParameters(parameters);
// issue 3914 - removed logic designed to remove any parameter of type HeaderParameter
return super.fromOperation(path, httpMethod, operation, definitions, swagger);
}

View File

@ -264,7 +264,10 @@ public class TizenClientCodegen extends DefaultCodegen implements CodegenConfig
}
@Override
public String escapeReservedWord(String name) {
public String escapeReservedWord(String name) {
if(this.reservedWordsMappings().containsKey(name)) {
return this.reservedWordsMappings().get(name);
}
return "_" + name;
}

View File

@ -3,6 +3,8 @@ package io.swagger.codegen.languages;
import java.io.File;
import io.swagger.codegen.SupportingFile;
import io.swagger.codegen.CodegenParameter;
import io.swagger.models.properties.Property;
public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCodegen {
@ -19,7 +21,10 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
@Override
public void processOpts() {
super.processOpts();
supportingFiles.add(new SupportingFile("api.d.mustache", apiPackage().replace('.', File.separatorChar), "api.d.ts"));
supportingFiles.add(new SupportingFile("models.mustache", modelPackage().replace('.', File.separatorChar), "models.ts"));
supportingFiles.add(new SupportingFile("apis.mustache", apiPackage().replace('.', File.separatorChar), "api.ts"));
supportingFiles.add(new SupportingFile("index.mustache", getIndexDirectory(), "index.ts"));
supportingFiles.add(new SupportingFile("api.module.mustache", getIndexDirectory(), "api.module.ts"));
supportingFiles.add(new SupportingFile("git_push.sh.mustache", "", "git_push.sh"));
supportingFiles.add(new SupportingFile("gitignore", "", ".gitignore"));
@ -29,9 +34,56 @@ public class TypeScriptAngularClientCodegen extends AbstractTypeScriptClientCode
super();
outputFolder = "generated-code/typescript-angular";
modelTemplateFiles.put("model.mustache", ".ts");
apiTemplateFiles.put("api.mustache", ".ts");
apiTemplateFiles.put("api.mustache", ".ts");
embeddedTemplateDir = templateDir = "typescript-angular";
apiPackage = "API.Client";
modelPackage = "API.Client";
apiPackage = "api";
modelPackage = "model";
}
@Override
public String getSwaggerType(Property p) {
String swaggerType = super.getSwaggerType(p);
if(isLanguagePrimitive(swaggerType) || isLanguageGenericType(swaggerType)) {
return swaggerType;
}
return addModelPrefix(swaggerType);
}
@Override
public void postProcessParameter(CodegenParameter parameter) {
super.postProcessParameter(parameter);
parameter.dataType = addModelPrefix(parameter.dataType);
}
private String getIndexDirectory() {
String indexPackage = modelPackage.substring(0, Math.max(0, modelPackage.lastIndexOf('.')));
return indexPackage.replace('.', File.separatorChar);
}
private String addModelPrefix(String swaggerType) {
String type = null;
if (typeMapping.containsKey(swaggerType)) {
type = typeMapping.get(swaggerType);
} else {
type = swaggerType;
}
if (!isLanguagePrimitive(type) && !isLanguageGenericType(type)) {
type = "models." + swaggerType;
}
return type;
}
private boolean isLanguagePrimitive(String type) {
return languageSpecificPrimitives.contains(type);
}
private boolean isLanguageGenericType(String type) {
for (String genericType: languageGenericTypes) {
if (type.startsWith(genericType + "<")) {
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,216 @@
package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.Operation;
import org.apache.commons.lang3.StringUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ZendExpressivePathHandlerServerCodegen extends AbstractPhpCodegen {
@Override
public CodegenType getTag() {
return CodegenType.SERVER;
}
@Override
public String getName() {
return "ze-ph";
}
@Override
public String getHelp() {
return "Generates PHP server stub using Zend Expressive ( https://zendframework.github.io/zend-expressive ) and Path Handler ( https://github.com/Articus/PathHandler ).";
}
public ZendExpressivePathHandlerServerCodegen() {
super();
embeddedTemplateDir = templateDir = "ze-ph";
invokerPackage = "App";
packagePath = "";
srcBasePath = "src" + File.separator + "App";
apiDirName = "Handler";
modelDirName = "DTO";
apiPackage = invokerPackage + "\\" + apiDirName;
modelPackage = invokerPackage + "\\" + modelDirName;
apiTestTemplateFiles.clear();
modelTestTemplateFiles.clear();
apiDocTemplateFiles.clear();
modelDocTemplateFiles.clear();
supportingFiles.add(new SupportingFile("README.md.mustache", packagePath, "README.md"));
supportingFiles.add(new SupportingFile("composer.json.mustache", packagePath, "composer.json"));
supportingFiles.add(new SupportingFile("index.php", packagePath + File.separator + "public", "index.php"));
supportingFiles.add(new SupportingFile("container.php", packagePath + File.separator + "application", "container.php"));
supportingFiles.add(new SupportingFile("config.yml", packagePath + File.separator + "application", "config.yml"));
supportingFiles.add(new SupportingFile("app.yml.mustache", packagePath + File.separator + "application" + File.separator + "config", "app.yml"));
supportingFiles.add(new SupportingFile("path_handler.yml.mustache", packagePath + File.separator + "application" + File.separator + "config", "path_handler.yml"));
supportingFiles.add(new SupportingFile("data_transfer.yml.mustache", packagePath + File.separator + "application" + File.separator + "config", "data_transfer.yml"));
supportingFiles.add(new SupportingFile("Date.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Strategy", "Date.php"));
supportingFiles.add(new SupportingFile("DateTime.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Strategy", "DateTime.php"));
supportingFiles.add(new SupportingFile("Type.php.mustache", packagePath + File.separator + srcBasePath + File.separator + "Validator", "Type.php"));
supportingFiles.add(new SupportingFile("ErrorMiddleware.php.mustache", packagePath + File.separator + srcBasePath, "ErrorMiddleware.php"));
additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, "1.0.0");
}
/**
* Add operation to group
* Override of default grouping - group by resource path, not tag
*
* @param tag name of the tag
* @param resourcePath path of the resource
* @param operation Swagger Operation object
* @param co Codegen Operation object
* @param operations map of Codegen operations
*/
@Override
public void addOperationToGroup(String tag, String resourcePath, Operation operation, CodegenOperation co, Map<String, List<CodegenOperation>> operations) {
List<CodegenOperation> opList = operations.get(resourcePath);
if (opList == null) {
opList = new ArrayList<CodegenOperation>();
operations.put(resourcePath, opList);
}
//ignore duplicate operation ids - that means that operation has several tags
int counter = 0;
for (CodegenOperation op : opList) {
if (co.operationId.equals(op.operationId)) {
counter++;
}
}
if (counter == 0) {
co.operationIdLowerCase = co.operationId.toLowerCase();
opList.add(co);
co.baseName = tag;
}
}
/**
* Return the file name of the Api Test
*
* @param name the file name of the Api
* @return the file name of the Api
*/
@Override
public String toApiFilename(String name) {
return toApiName(name);
}
/**
* Output the API (class) name (capitalized) ending with "Api"
* Return DefaultApi if name is empty
*
* @param name the name of the Api
* @return capitalized Api name ending with "Api"
*/
@Override
public String toApiName(String name) {
//Remove }
name = name.replaceAll("[\\}]", "");
return super.toModelName(name);
}
@Override
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
objs = super.postProcessOperations(objs);
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
String interfaceToImplement;
StringBuilder interfacesToImplement = new StringBuilder();
String classMethod;
for (CodegenOperation op : operationList) {
switch (op.httpMethod) {
case "GET":
interfaceToImplement = "Operation\\GetInterface";
classMethod = "handleGet";
break;
case "POST":
interfaceToImplement = "Operation\\PostInterface";
classMethod = "handlePost";
break;
case "PATCH":
interfaceToImplement = "Operation\\PatchInterface";
classMethod = "handlePatch";
break;
case "PUT":
interfaceToImplement = "Operation\\PutInterface";
classMethod = "handlePut";
break;
case "DELETE":
interfaceToImplement = "Operation\\DeleteInterface";
classMethod = "handleDelete";
break;
default:
throw new RuntimeException("Unknown HTTP Method " + op.httpMethod + " not allowed");
}
if (interfacesToImplement.length() > 0) {
interfacesToImplement.append(", ");
}
interfacesToImplement.append(interfaceToImplement);
op.httpMethod = classMethod;
}
operations.put("interfacesToImplement", interfacesToImplement.toString());
return objs;
}
@Override
public Map<String, Object> postProcessSupportingFileData(Map<String, Object> objs) {
objs = super.postProcessSupportingFileData(objs);
Map<String, Object> apiInfo = (Map<String, Object>) objs.get("apiInfo");
List<Map<String, Object>> apis = (List<Map<String, Object>>) apiInfo.get("apis");
List<Map<String, Object>> routes = new ArrayList<Map<String, Object>>();
for (Map<String, Object> api : apis) {
String handler = (String) api.get("classname");
String url = (String) api.get("baseName");
if (url.charAt(0) == '/') {
url = url.substring(1);
}
insertRoute(routes, url.split("/"), 0, handler);
}
objs.put("routes", routes);
return objs;
}
private void insertRoute(List<Map<String, Object>> routes, String[] urlParts, int currentUrlPartIndex, String handler) {
if (urlParts.length > currentUrlPartIndex) {
String urlPart = urlParts[currentUrlPartIndex];
//List<Map<String, Object>> subRoutes = null;
Map<String, Object> currentRoute = null;
for (Map<String, Object> route : routes) {
if (urlPart.equals(route.get("name"))) {
currentRoute = route;
break;
}
}
if (currentRoute == null) {
currentRoute = new HashMap<String, Object>();
String routePart = urlPart.replaceAll("^\\{(\\w+)\\}$", ":$1");
boolean isLastUrlPart = currentUrlPartIndex == urlParts.length - 1;
currentRoute.put("name", urlPart);
currentRoute.put("route", "/" + routePart);
currentRoute.put("type", (urlPart == routePart) ? "Literal" : "Segment");
currentRoute.put("handler", isLastUrlPart ? handler : null);
currentRoute.put("hasChildren", false);
currentRoute.put("children", new ArrayList<Map<String, Object>>());
currentRoute.put("padding", StringUtils.repeat(' ', 4 * currentUrlPartIndex));
routes.add(currentRoute);
}
List<Map<String, Object>> subRoutes = (List<Map<String, Object>>) currentRoute.get("children");
insertRoute(subRoutes, urlParts, currentUrlPartIndex + 1, handler);
currentRoute.put("hasChildren", !subRoutes.isEmpty());
}
}
}

View File

@ -15,10 +15,18 @@ public interface CXFServerFeatures
public static final String ADD_CONSUMES_PRODUCES_JSON = "addConsumesProducesJson";
public static final String USE_ANNOTATED_BASE_PATH = "useAnnotatedBasePath";
public static final String GENERATE_NON_SPRING_APPLICATION = "generateNonSpringApplication";
public void setUseWadlFeature(boolean useWadlFeature);
public void setUseMultipartFeature(boolean useMultipartFeature);
public void setAddConsumesProducesJson(boolean addConsumesProducesJson);
public void setUseAnnotatedBasePath(boolean useAnnotatedBasePath);
public void setGenerateNonSpringApplication(boolean generateNonSpringApplication);
}

View File

@ -1,9 +1,10 @@
package io.swagger.codegen.utils;
import org.apache.commons.lang3.tuple.Pair;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import joptsimple.internal.Strings;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
@ -22,10 +23,10 @@ public class OptionUtils {
results.add(pair);
}
}
//Strings.isNullOrEmpty(input)
return results;
}
public static List<String> splitCommaSeparatedList(String input) {
List<String> results = new ArrayList<String>();
@ -39,5 +40,4 @@ public class OptionUtils {
return results;
}
}

View File

@ -116,6 +116,7 @@ public class ApiClient {
* Build the Client used to make HTTP requests with the latest settings,
* i.e. objectMapper and debugging.
* TODO: better to use the Builder Pattern?
* @return API client
*/
public ApiClient rebuildHttpClient() {
// Add the JSON serialization support to Jersey
@ -136,6 +137,7 @@ public class ApiClient {
* Note: If you make changes to the object mapper, remember to set it back via
* <code>setObjectMapper</code> in order to trigger HTTP client rebuilding.
* </p>
* @return Object mapper
*/
public ObjectMapper getObjectMapper() {
return objectMapper;
@ -168,6 +170,7 @@ public class ApiClient {
/**
* Gets the status code of the previous request
* @return Status code
*/
public int getStatusCode() {
return statusCode;
@ -175,6 +178,7 @@ public class ApiClient {
/**
* Gets the response headers of the previous request
* @return Response headers
*/
public Map<String, List<String>> getResponseHeaders() {
return responseHeaders;
@ -182,6 +186,7 @@ public class ApiClient {
/**
* Get authentications (key: authentication name, value: authentication).
* @return Map of authentication
*/
public Map<String, Authentication> getAuthentications() {
return authentications;
@ -199,6 +204,7 @@ public class ApiClient {
/**
* Helper method to set username for the first HTTP basic authentication.
* @param username Username
*/
public void setUsername(String username) {
for (Authentication auth : authentications.values()) {
@ -212,6 +218,7 @@ public class ApiClient {
/**
* Helper method to set password for the first HTTP basic authentication.
* @param password Password
*/
public void setPassword(String password) {
for (Authentication auth : authentications.values()) {
@ -225,6 +232,7 @@ public class ApiClient {
/**
* Helper method to set API key value for the first API key authentication.
* @param apiKey API key
*/
public void setApiKey(String apiKey) {
for (Authentication auth : authentications.values()) {
@ -238,6 +246,7 @@ public class ApiClient {
/**
* Helper method to set API key prefix for the first API key authentication.
* @param apiKeyPrefix API key prefix
*/
public void setApiKeyPrefix(String apiKeyPrefix) {
for (Authentication auth : authentications.values()) {
@ -251,6 +260,7 @@ public class ApiClient {
/**
* Helper method to set access token for the first OAuth2 authentication.
* @param accessToken Access token
*/
public void setAccessToken(String accessToken) {
for (Authentication auth : authentications.values()) {
@ -264,6 +274,8 @@ public class ApiClient {
/**
* Set the User-Agent header's value (by adding to the default header map).
* @param userAgent User agent
* @return API client
*/
public ApiClient setUserAgent(String userAgent) {
addDefaultHeader("User-Agent", userAgent);
@ -275,6 +287,7 @@ public class ApiClient {
*
* @param key The header's key
* @param value The header's value
* @return API client
*/
public ApiClient addDefaultHeader(String key, String value) {
defaultHeaderMap.put(key, value);
@ -283,6 +296,7 @@ public class ApiClient {
/**
* Check that whether debugging is enabled for this API client.
* @return True if debugging is on
*/
public boolean isDebugging() {
return debugging;
@ -292,6 +306,7 @@ public class ApiClient {
* Enable/disable debugging for this API client.
*
* @param debugging To enable (true) or disable (false) debugging
* @return API client
*/
public ApiClient setDebugging(boolean debugging) {
this.debugging = debugging;
@ -302,6 +317,7 @@ public class ApiClient {
/**
* Connect timeout (in milliseconds).
* @return Connection timeout
*/
public int getConnectTimeout() {
return connectionTimeout;
@ -311,6 +327,8 @@ public class ApiClient {
* Set the connect timeout (in milliseconds).
* A value of 0 means no timeout, otherwise values must be between 1 and
* {@link Integer#MAX_VALUE}.
* @param connectionTimeout Connection timeout in milliseconds
* @return API client
*/
public ApiClient setConnectTimeout(int connectionTimeout) {
this.connectionTimeout = connectionTimeout;
@ -320,6 +338,7 @@ public class ApiClient {
/**
* Get the date format used to parse/format date parameters.
* @return Date format
*/
public DateFormat getDateFormat() {
return dateFormat;
@ -327,6 +346,8 @@ public class ApiClient {
/**
* Set the date format used to parse/format date parameters.
* @param dateFormat Date format
* @return API client
*/
public ApiClient setDateFormat(DateFormat dateFormat) {
this.dateFormat = dateFormat;
@ -339,6 +360,8 @@ public class ApiClient {
/**
* Parse the given string into Date object.
* @param str String
* @return Date
*/
public Date parseDate(String str) {
try {
@ -350,6 +373,8 @@ public class ApiClient {
/**
* Format the given Date object into string.
* @param date Date
* @return Date in string format
*/
public String formatDate(Date date) {
return dateFormat.format(date);
@ -357,6 +382,8 @@ public class ApiClient {
/**
* Format the given parameter object into string.
* @param param Object
* @return Object in string format
*/
public String parameterToString(Object param) {
if (param == null) {
@ -378,8 +405,12 @@ public class ApiClient {
}
/*
Format to {@code Pair} objects.
*/
* Format to {@code Pair} objects.
* @param collectionFormat Collection format
* @param name Name
* @param value Value
* @return List of pair
*/
public List<Pair> parameterToPairs(String collectionFormat, String name, Object value){
List<Pair> params = new ArrayList<Pair>();
@ -439,6 +470,8 @@ public class ApiClient {
* application/json
* application/json; charset=UTF8
* APPLICATION/JSON
* @param mime MIME
* @return True if MIME type is boolean
*/
public boolean isJsonMime(String mime) {
return mime != null && mime.matches("(?i)application\\/json(;.*)?");
@ -488,6 +521,8 @@ public class ApiClient {
/**
* Escape the given string to be used as URL query value.
* @param str String
* @return Escaped string
*/
public String escapeString(String str) {
try {
@ -500,6 +535,11 @@ public class ApiClient {
/**
* Serialize the given Java object into string according the given
* Content-Type (only JSON is supported for now).
* @param obj Object
* @param contentType Content type
* @param formParams Form parameters
* @return Object
* @throws ApiException API exception
*/
public Object serialize(Object obj, String contentType, Map<String, Object> formParams) throws ApiException {
if (contentType.startsWith("multipart/form-data")) {
@ -605,6 +645,7 @@ public class ApiClient {
/**
* Invoke API by sending HTTP request with the given options.
*
* @param <T> Type
* @param path The sub-path of the HTTP URL
* @param method The request method, one of "GET", "POST", "PUT", and "DELETE"
* @param queryParams The query parameters
@ -614,7 +655,9 @@ public class ApiClient {
* @param accept The request's Accept header
* @param contentType The request's Content-Type header
* @param authNames The authentications to apply
* @param returnType Return type
* @return The response body in type of string
* @throws ApiException API exception
*/
public <T> T invokeAPI(String path, String method, List<Pair> queryParams, Object body, Map<String, String> headerParams, Map<String, Object> formParams, String accept, String contentType, String[] authNames, GenericType<T> returnType) throws ApiException {
@ -653,6 +696,8 @@ public class ApiClient {
* Update query and header parameters based on authentication settings.
*
* @param authNames The authentications to apply
* @param queryParams Query parameters
* @param headerParams Header parameters
*/
private void updateParamsForAuth(String[] authNames, List<Pair> queryParams, Map<String, String> headerParams) {
for (String authName : authNames) {
@ -664,6 +709,8 @@ public class ApiClient {
/**
* Encode the given form parameters as request body.
* @param formParams Form parameters
* @return HTTP form encoded parameters
*/
private String getXWWWFormUrlencodedParams(Map<String, Object> formParams) {
StringBuilder formParamBuilder = new StringBuilder();

View File

@ -44,9 +44,13 @@ public class {{classname}} {
{{#operation}}
/**
* {{summary}}
* {{notes}}{{#allParams}}
* @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}{{/allParams}}{{#returnType}}
* @return {{{returnType}}}{{/returnType}}
* {{notes}}
{{#allParams}}
* @param {{paramName}} {{description}}{{#required}} (required){{/required}}{{^required}} (optional{{#defaultValue}}, default to {{{.}}}{{/defaultValue}}){{/required}}
{{/allParams}}
{{#returnType}}
* @return {{returnType}}
{{/returnType}}
* @throws ApiException if fails to make API call
*/
public {{#returnType}}{{{returnType}}} {{/returnType}}{{^returnType}}void {{/returnType}}{{operationId}}({{#allParams}}{{{dataType}}} {{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) throws ApiException {

View File

@ -1,45 +1,45 @@
{{>licenseInfo}}
package {{package}};
import {{invokerPackage}}.ApiException;
{{#imports}}import {{import}};
{{/imports}}
import org.junit.Test;
import org.junit.Ignore;
{{^fullJavaUtil}}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
{{/fullJavaUtil}}
/**
* API tests for {{classname}}
*/
@Ignore
public class {{classname}}Test {
private final {{classname}} api = new {{classname}}();
{{#operations}}{{#operation}}
/**
* {{summary}}
*
* {{notes}}
*
* @throws ApiException
* if the Api call fails
*/
@Test
public void {{operationId}}Test() throws ApiException {
{{#allParams}}
{{{dataType}}} {{paramName}} = null;
{{/allParams}}
{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
// TODO: test validations
}
{{/operation}}{{/operations}}
}
{{>licenseInfo}}
package {{package}};
import {{invokerPackage}}.ApiException;
{{#imports}}import {{import}};
{{/imports}}
import org.junit.Test;
import org.junit.Ignore;
{{^fullJavaUtil}}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
{{/fullJavaUtil}}
/**
* API tests for {{classname}}
*/
@Ignore
public class {{classname}}Test {
private final {{classname}} api = new {{classname}}();
{{#operations}}{{#operation}}
/**
* {{summary}}
*
* {{notes}}
*
* @throws ApiException
* if the Api call fails
*/
@Test
public void {{operationId}}Test() throws ApiException {
{{#allParams}}
{{{dataType}}} {{paramName}} = null;
{{/allParams}}
{{#returnType}}{{{returnType}}} response = {{/returnType}}api.{{operationId}}({{#allParams}}{{paramName}}{{#hasMore}}, {{/hasMore}}{{/allParams}});
// TODO: test validations
}
{{/operation}}{{/operations}}
}

View File

@ -32,21 +32,22 @@
{{^minItems}}
{{#maxItems}}
@Size(max={{maxItems}})
{{/maxItems}}
{{/minItems}}
{{/maxItems}}
{{/minItems}}
{{! check for integer / number=decimal type}}
{{#isInteger}}
{{#minimum}}
{{#isInteger}}
@Min({{minimum}})
{{/isInteger}}
{{#isLong}}
@Min({{minimum}})
{{/isLong}}
{{/minimum}}
{{#maximum}}
{{#isInteger}}
@Max({{maximum}})
{{/isInteger}}
{{#isLong}}
@Max({{maximum}})
{{/isLong}}
{{/maximum}}
{{/isInteger}}
{{^isInteger}}
{{#minimum}}
@DecimalMin("{{minimum}}")
{{/minimum}}
{{#maximum}}
@DecimalMax("{{maximum}}")
{{/maximum}}
{{/isInteger}}

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