Merge branch 'master' of github.com:wordnik/swagger-codegen

This commit is contained in:
Tony Tam 2014-05-01 20:17:53 -07:00
commit 46023c47f5
9 changed files with 166 additions and 142 deletions

11
LICENSE Normal file
View File

@ -0,0 +1,11 @@
Copyright 2014 Reverb Technologies, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at [apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -4,8 +4,15 @@
## Overview
This is the swagger codegen project, which allows generation of client libraries automatically from a
Swagger-compliant server. You can find out more about both the spec and the framework at
http://swagger.wordnik.com. For more information about Wordnik's APIs, please visit http://developer.wordnik.com.
Swagger-compliant server.
## What's Swagger?
The goal of Swagger™ is to define a standard, language-agnostic interface to REST APIs which allows both humans and computers to discover and understand the capabilities of the service without access to source code, documentation, or through network traffic inspection. When properly defined via Swagger, a consumer can understand and interact with the remote service with a minimal amount of implementation logic. Similar to what interfaces have done for lower-level programming, Swager removes the guesswork in calling the service.
Check out [Swagger-Spec](https://github.com/wordnik/swagger-spec) for additional information about the Swagger project, including additional libraries with support for other languages and more.
### Prerequisites
You need the following installed and available in your $PATH:
@ -224,7 +231,7 @@ either repackage the library OR modify your codegen script to use a file path!
License
-------
Copyright 2013 Wordnik, Inc.
Copyright 2014 Wordnik, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.

View File

@ -1,7 +1,6 @@
#!/bin/sh
SCRIPT="$0"
SCALA_RUNNER_VERSION=$(scala ./bin/Version.scala)
while [ -h "$SCRIPT" ] ; do
ls=`ls -ld "$SCRIPT"`
@ -19,6 +18,7 @@ if [ ! -d "${APP_DIR}" ]; then
fi
cd $APP_DIR
SCALA_RUNNER_VERSION=$(scala ./bin/Version.scala)
# if you've executed sbt assembly previously it will use that instead.
@ -26,7 +26,7 @@ export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/
ags="$@"
if [ -f $APP_DIR/target/scala-$SCALA_RUNNER_VERSION/swagger-codegen.jar ]; then
scala -cp target/scala-$SCALA_RUNNER_VERSION/swagger-codegen.jar $ags
scala -cp $APP_DIR/target/scala-$SCALA_RUNNER_VERSION/swagger-codegen.jar $ags
else
echo "Please set scalaVersion := \"$SCALA_RUNNER_VERSION\" in build.sbt and run ./sbt assembly"
fi

View File

@ -22,8 +22,8 @@ cd $APP_DIR
# 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 -DfileMap=samples/client/wordnik-api/spec-files"
ags="$@ SwaggerDocGenerator http://developer.wordnik.com/v4/resources.json"
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties -DfileMap=samples/client/wordnik-api/spec-files/resources.json"
ags="$@ SwaggerDocGenerator https://api.wordnik.com/v4/resources.json"
if [ -f $APP_DIR/target/scala-$SCALA_RUNNER_VERSION/swagger-codegen.jar ]; then
scala -cp target/scala-$SCALA_RUNNER_VERSION/swagger-codegen.jar $ags

View File

@ -170,13 +170,13 @@
</dependency>
<dependency>
<groupId>com.wordnik</groupId>
<artifactId>swagger-core_2.9.1</artifactId>
<artifactId>swagger-core_${scala-short-version}</artifactId>
<version>${swagger-core-version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.scalatest</groupId>
<artifactId>scalatest_2.9.1</artifactId>
<artifactId>scalatest_${scala-short-version}</artifactId>
<version>${scala-test-version}</version>
<scope>test</scope>
</dependency>
@ -187,15 +187,34 @@
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>scala_2.10</id>
<properties>
<scala-version>2.10.3</scala-version>
<scala-short-version>2.10</scala-short-version>
<swagger-core-version>1.3.2</swagger-core-version>
<scala-test-version>2.1.2</scala-test-version>
</properties>
</profile>
<profile>
<id>scala_2.9.1</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<scala-version>2.9.1-1</scala-version>
<scala-short-version>2.9.1</scala-short-version>
<swagger-core-version>1.1.0</swagger-core-version>
<scala-test-version>1.6.1</scala-test-version>
</properties>
</profile>
</profiles>
<properties>
<jersey-version>1.7</jersey-version>
<swagger-core-version>1.1.0</swagger-core-version>
<scala-version>2.9.1-1</scala-version>
<junit-version>4.8.1</junit-version>
<maven-plugin.version>1.0.0</maven-plugin.version>
<scala-test-version>1.6.1</scala-test-version>
<junit-version>4.8.1</junit-version>
<scala-test-version>1.6.1</scala-test-version>
<scala-maven-plugin-version>3.1.5</scala-maven-plugin-version>
</properties>
</project>

View File

@ -72,7 +72,7 @@ class BasicAndroidJavaGenerator extends BasicJavaGenerator {
("httpPatch.mustache", destinationDir + java.io.File.separator + invokerPackage.get.replace(".", java.io.File.separator) + java.io.File.separator, "HttpPatch.java"),
("apiInvoker.mustache", destinationDir + java.io.File.separator + invokerPackage.get.replace(".", java.io.File.separator) + java.io.File.separator, "ApiInvoker.java"),
("jsonUtil.mustache", destinationDir + java.io.File.separator + invokerPackage.get.replace(".", java.io.File.separator) + java.io.File.separator, "JsonUtil.java"),
("ApiException.mustache", destinationDir + java.io.File.separator + invokerPackage.get.replace(".", java.io.File.separator) + java.io.File.separator, "ApiException.java"),
("apiException.mustache", destinationDir + java.io.File.separator + invokerPackage.get.replace(".", java.io.File.separator) + java.io.File.separator, "ApiException.java"),
("pom.mustache", destinationDir, "pom.xml")
)
}
}

View File

@ -43,12 +43,12 @@ abstract class BasicGenerator extends CodegenConfig with PathUtil {
var codegen = new Codegen(this)
def generateClient(args: Array[String]) = {
def generateClient(args: Array[String]): Unit = {
generateClientWithoutExit(args)
System.exit(0)
}
def generateClientWithoutExit(args: Array[String]) {
def generateClientWithoutExit(args: Array[String]): Seq[File] = {
if (args.length == 0) {
throw new RuntimeException("Need url to resource listing as argument. You can also specify VM Argument -DfileMap=/path/to/folder/containing.resources.json/")
}

View File

@ -81,12 +81,12 @@ class Codegen(config: CodegenConfig) {
lb
})
opList += apiToMap(apiPath, operation)
CoreUtils.extractModelNames(operation).foreach(i => allImports += i)
}
})
}
case None =>
}
@ -223,14 +223,14 @@ class Codegen(config: CodegenConfig) {
var paramList = new ListBuffer[HashMap[String, AnyRef]]
var errorList = new ListBuffer[HashMap[String, AnyRef]]
var bodyParamRequired: Option[String] = Some("true")
if (operation.responseMessages != null) {
operation.responseMessages.foreach(param => {
operation.responseMessages.foreach(param => {
val params = new HashMap[String, AnyRef]
params += "code" -> param.code.toString()
params += "reason" -> param.message
params += "hasMore" -> "true"
errorList += params
errorList += params
})
}
@ -509,7 +509,7 @@ class Codegen(config: CodegenConfig) {
"defaultValue" -> config.toDeclaration(propertyDocSchema)._2,
"description" -> propertyDocSchema.description,
"notes" -> propertyDocSchema.description,
"allowableValues" -> rawAllowableValuesToString(propertyDocSchema.allowableValues),
"allowableValues" -> rawAllowableValuesToString(propertyDocSchema.allowableValues),
(if(propertyDocSchema.required) "required" else "isNotRequired") -> "true",
"getter" -> config.toGetter(prop._1, config.toDeclaration(propertyDocSchema)._1),
"setter" -> config.toSetter(prop._1, config.toDeclaration(propertyDocSchema)._1),
@ -555,87 +555,110 @@ class Codegen(config: CodegenConfig) {
write(m)
}
def writeSupportingClasses(apis: Map[(String, String), List[(String, Operation)]], models: Map[String, Model], apiVersion: String) = {
val rootDir = new java.io.File(".")
val engine = new TemplateEngine(Some(rootDir))
final def writeSupportingClasses(
apis: Map[(String, String), List[(String, Operation)]],
models: Map[String, Model],
apiVersion: String,
rootDir: Option[File],
dataF: (Map[(String, String), List[(String, Operation)]], Map[String, Model]) => Map[String, AnyRef]): Seq[File] = {
val apiList = new ListBuffer[Map[String, AnyRef]]
apis.foreach(a => {
apiList += Map(
"name" -> a._1._2,
"filename" -> config.toApiFilename(a._1._2),
"className" -> config.toApiName(a._1._2),
"basePath" -> a._1._1,
"operations" -> {
(for (t <- a._2) yield { Map("operation" -> t._2, "path" -> t._1) }).toList
})
})
val engine = new TemplateEngine(rootDir orElse Some(new File(".")))
val data = dataF(apis, models)
val modelList = new ListBuffer[HashMap[String, AnyRef]]
models.foreach(m => {
val json = writeJson(m._2)
modelList += HashMap(
"modelName" -> m._1,
"model" -> modelToMap(m._1, m._2),
"filename" -> config.toModelFilename(m._1),
"modelJson" -> json,
"hasMoreModels" -> "true")
})
modelList.size match {
case 0 =>
case _ => modelList.last.asInstanceOf[HashMap[String, String]] -= "hasMoreModels"
}
val data: HashMap[String, AnyRef] =
HashMap(
"invokerPackage" -> config.invokerPackage,
"package" -> config.packageName,
"modelPackage" -> config.modelPackage,
"apiPackage" -> config.apiPackage,
"apis" -> apiList,
"models" -> modelList,
"apiVersion" -> apiVersion) ++ config.additionalParams
config.supportingFiles.map(file => {
val outputFiles = config.supportingFiles map { file =>
val supportingFile = file._1
val outputDir = file._2
val destFile = file._3
val outputFilename = outputDir + File.separator + destFile
val outputFolder = new File(outputFilename).getParent
val outputFile = new File(outputDir.replaceAll("\\.", File.separator) + File.separator + destFile)
val outputFolder = outputFile.getParent
new File(outputFolder).mkdirs
if (supportingFile.endsWith(".mustache")) {
val output = {
val (resourceName, (_, template)) = compileTemplate(supportingFile, Some(rootDir), Some(engine))
val (resourceName, (_, template)) = compileTemplate(supportingFile, rootDir, Some(engine))
engine.layout(resourceName, template, data.toMap)
}
val fw = new FileWriter(outputFilename, false)
val fw = new FileWriter(outputFile, false)
fw.write(output + "\n")
fw.close()
println("wrote " + outputFilename)
println("wrote " + outputFile.getPath())
} else {
val file = new File(config.templateDir + File.separator + supportingFile)
if(file.isDirectory()) {
if (file.isDirectory()) {
// copy the whole directory
FileUtils.copyDirectory(file, new File(outputDir))
println("copied directory " + supportingFile)
} else {
val is = getInputStream(config.templateDir + File.separator + supportingFile)
val outputFile = new File(outputFilename)
val parentDir = new File(outputFile.getParent)
val parentDir = outputFile.getParentFile()
if (parentDir != null && !parentDir.exists) {
println("making directory: " + parentDir.toString + ": " + parentDir.mkdirs)
}
FileUtils.copyInputStreamToFile(is, new File(outputFilename))
println("copied " + outputFilename)
FileUtils.copyInputStreamToFile(is, outputFile)
println("copied " + outputFile.getPath())
is.close
}
}
})
outputFile
}
//a shutdown method will be added to scalate in an upcoming release
engine.compiler.shutdown()
outputFiles
}
def writeSupportingClasses(apis: Map[(String, String), List[(String, Operation)]],
models: Map[String, Model], apiVersion: String): Seq[File] = {
val rootDir: Option[File] = Some(new File("."))
def apiListF(apis: Map[(String, String), List[(String, Operation)]]): List[Map[String, AnyRef]] = {
val apiList = new ListBuffer[Map[String, AnyRef]]
apis.foreach(a => {
apiList += Map(
"name" -> a._1._2,
"filename" -> config.toApiFilename(a._1._2),
"className" -> config.toApiName(a._1._2),
"basePath" -> a._1._1,
"operations" -> {
(for (t <- a._2) yield { Map("operation" -> apiToMap(t._1, t._2), "path" -> t._1) }).toList
})
})
apiList.toList
}
def modelListF(models: Map[String, Model]): List[Map[String, AnyRef]] = {
val modelList = new ListBuffer[HashMap[String, AnyRef]]
models.foreach(m => {
val json = writeJson(m._2)
modelList += HashMap(
"modelName" -> m._1,
"model" -> modelToMap(m._1, m._2),
"filename" -> config.toModelFilename(m._1),
"modelJson" -> json,
"hasMoreModels" -> "true")
})
modelList.size match {
case 0 =>
case _ => modelList.last.asInstanceOf[HashMap[String, String]] -= "hasMoreModels"
}
modelList.map(_.toMap).toList
}
def dataF(apis: Map[(String, String), List[(String, Operation)]],
models: Map[String, Model]): Map[String, AnyRef] =
Map(
"invokerPackage" -> config.invokerPackage,
"package" -> config.packageName,
"modelPackage" -> config.modelPackage,
"apiPackage" -> config.apiPackage,
"apis" -> apiListF(apis),
"models" -> modelListF(models),
"apiVersion" -> apiVersion) ++ config.additionalParams
writeSupportingClasses(apis, models, apiVersion, rootDir, dataF)
}
protected def isListType(dt: String) = isCollectionType(dt, "List") || isCollectionType(dt, "Array") || isCollectionType(dt, "Set")

View File

@ -114,91 +114,55 @@ object ScalaAsyncClientGenerator extends App {
}
class AsyncClientCodegen(clientName: String, config: CodegenConfig, rootDir: Option[File] = None) extends Codegen(config) {
override def writeSupportingClasses(apis: Map[(String, String), List[(String, Operation)]], models: Map[String, Model], apiVersion: String) = {
val engine = new TemplateEngine(rootDir orElse Some(new File(".")))
val apiList = new ListBuffer[Map[String, AnyRef]]
override def writeSupportingClasses(apis: Map[(String, String), List[(String, Operation)]],
models: Map[String, Model], apiVersion: String): Seq[File] = {
apis.map(a => {
apiList += Map(
"name" -> a._1._2,
"filename" -> config.toApiFilename(a._1._2),
"className" -> config.toApiName(a._1._2),
"basePath" -> a._1._1,
"operations" -> {
(for (t <- a._2) yield { Map("operation" -> t._2, "path" -> t._1) }).toList
})
})
val modelList = new ListBuffer[HashMap[String, AnyRef]]
models.foreach(m => {
val json = write(m._2)
def apiListF(apis: Map[(String, String), List[(String, Operation)]]): List[Map[String, AnyRef]] = {
val apiList = new ListBuffer[Map[String, AnyRef]]
apis.map(a => {
apiList += Map(
"name" -> a._1._2,
"filename" -> config.toApiFilename(a._1._2),
"className" -> config.toApiName(a._1._2),
"basePath" -> a._1._1,
"operations" -> {
(for (t <- a._2) yield { Map("operation" -> t._2, "path" -> t._1) }).toList
})
})
apiList.toList
}
def modelListF(models: Map[String, Model]): List[Map[String, AnyRef]] = {
val modelList = new ListBuffer[HashMap[String, AnyRef]]
models.foreach(m => {
val json = write(m._2)
modelList += HashMap(
"modelName" -> m._1,
"model" -> m._2,
"filename" -> config.toModelFilename(m._1),
"modelJson" -> json,
"hasMore" -> "true")
})
modelList.size match {
case 0 =>
case _ => modelList.last.asInstanceOf[HashMap[String, String]] -= "hasMore"
})
modelList.size match {
case 0 =>
case _ => modelList.last.asInstanceOf[HashMap[String, String]] -= "hasMore"
}
modelList.map(_.toMap).toList
}
val data =
def dataF(apis: Map[(String, String), List[(String, Operation)]],
models: Map[String, Model]): Map[String, AnyRef] =
Map(
"clientName" -> clientName.underscore.pascalize,
"projectName" -> clientName.underscore.dasherize,
"package" -> config.packageName,
"modelPackage" -> config.modelPackage,
"apiPackage" -> config.apiPackage,
"apis" -> apiList,
"models" -> modelList)
"apis" -> apiListF(apis),
"models" -> modelListF(models))
config.supportingFiles.map(file => {
val supportingFile = file._1
val outputDir = file._2
val destFile = file._3
val outputFilename = outputDir.replaceAll("\\.", File.separator) + File.separator + destFile
val outputFolder = new File(outputFilename).getParent
new File(outputFolder).mkdirs
if (supportingFile.endsWith(".mustache")) {
val output = {
val (resourceName, (_, template)) = compileTemplate(supportingFile, rootDir, Some(engine))
engine.layout(resourceName, template, data.toMap)
}
val fw = new FileWriter(outputFilename, false)
fw.write(output + "\n")
fw.close()
println("wrote " + outputFilename)
} else {
val file = new File(config.templateDir + File.separator + supportingFile)
if(file.isDirectory) {
// copy the whole directory
FileUtils.copyDirectory(file, new File(outputDir))
println("copied directory " + supportingFile)
} else {
val is = getInputStream(config.templateDir + File.separator + supportingFile)
val outputFile = new File(outputFilename)
val parentDir = new File(outputFile.getParent)
if (parentDir != null && !parentDir.exists) {
println("making directory: " + parentDir.toString + ": " + parentDir.mkdirs)
}
FileUtils.copyInputStreamToFile(is, new File(outputFilename))
println("copied " + outputFilename)
is.close
}
}
})
//a shutdown method will be added to scalate in an upcoming release
engine.compiler.shutdown()
writeSupportingClasses(apis, models, apiVersion, rootDir, dataF)
}
override protected def compileTemplate(templateFile: String, rootDir: Option[File] = None, engine: Option[TemplateEngine] = None): (String, (TemplateEngine, Template)) = {