removed cruft

This commit is contained in:
Tony Tam 2015-02-16 22:06:10 -08:00
parent 66c6662f42
commit 97fca910a1
19 changed files with 653 additions and 3954 deletions

137
build.sbt
View File

@ -1,137 +0,0 @@
import xml.Group
import AssemblyKeys._
organization := "com.wordnik"
name := "swagger-codegen"
version := "2.0.18-SNAPSHOT"
crossVersion := CrossVersion.full
javacOptions ++= Seq("-target", "1.6", "-source", "1.6", "-Xlint:unchecked", "-Xlint:deprecation")
scalacOptions ++= Seq("-optimize", "-unchecked", "-deprecation", "-Xcheckinit", "-encoding", "utf8")
crossScalaVersions := Seq("2.10.4", "2.11.0", "2.11.1")
scalaVersion := "2.10.4"
libraryDependencies ++= Seq(
"org.json4s" %% "json4s-jackson" % "3.2.10",
"io.backchat.inflector" %% "scala-inflector" % "1.3.5",
"commons-io" % "commons-io" % "2.3",
"net.iharder" % "base64" % "2.3.8",
"ch.qos.logback" % "logback-classic" % "1.0.13" % "provided",
"org.rogach" %% "scallop" % "0.9.5",
"junit" % "junit" % "4.11" % "test",
"org.scalatest" %% "scalatest" % "2.1.7" % "test"
)
libraryDependencies <+= scalaVersion {
case v if v.startsWith("2.9") =>
"org.fusesource.scalate" % "scalate-core_2.9" % "1.6.1"
case v if v.startsWith("2.10") =>
"org.scalatra.scalate" %% "scalate-core" % "1.7.0"
case v if v.startsWith("2.11") =>
"org.scalatra.scalate" %% "scalate-core" % "1.7.0"
}
libraryDependencies ++= {
scalaVersion.toString match {
case v if v.startsWith("2.10") || v.startsWith("2.11") => Seq("org.scala-lang" % "scala-reflect" % v)
case _ => Seq()
}
}
resolvers += "Typesafe releases" at "http://repo.typesafe.com/typesafe/releases"
packageOptions <+= (name, version, organization) map {
(title, version, vendor) =>
Package.ManifestAttributes(
"Created-By" -> "Simple Build Tool",
"Built-By" -> System.getProperty("user.name"),
"Build-Jdk" -> System.getProperty("java.version"),
"Specification-Title" -> title,
"Specification-Version" -> version,
"Specification-Vendor" -> vendor,
"Implementation-Title" -> title,
"Implementation-Version" -> version,
"Implementation-Vendor-Id" -> vendor,
"Implementation-Vendor" -> vendor
)
}
publishTo <<= (version) { version: String =>
if (version.trim.endsWith("SNAPSHOT"))
Some("Sonatype Nexus Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots")
else
Some("Sonatype Nexus Releases" at "https://oss.sonatype.org/service/local/staging/deploy/maven2")
}
// publishTo := Some(Resolver.file("file", new File(Path.userHome.absolutePath+"/.m2/repository")))
artifact in (Compile, assembly) ~= { art =>
art.copy(`classifier` = Some("assembly"))
}
addArtifact(artifact in (Compile, assembly), assembly)
publishMavenStyle := true
publishArtifact in Test := false
pomIncludeRepository := { x => false }
credentials += Credentials(Path.userHome / ".ivy2" / ".credentials")
homepage := Some(new URL("https://github.com/wordnik/swagger-codegen"))
parallelExecution in Test := false
startYear := Some(2009)
licenses := Seq(("Apache License 2.0", new URL("http://www.apache.org/licenses/LICENSE-2.0.html")))
pomExtra <<= (pomExtra, name, description) {(pom, name, desc) => pom ++ Group(
<scm>
<connection>scm:git:git@github.com:wordnik/swagger-codegen.git</connection>
<developerConnection>scm:git:git@github.com:wordnik/swagger-codegen.git</developerConnection>
<url>https://github.com/wordnik/swagger-codegen</url>
</scm>
<issueManagement>
<system>github</system>
<url>https://github.com/wordnik/swagger-codegen/issues</url>
</issueManagement>
<developers>
<developer>
<id>rpidikiti</id>
<name>Ramesh Pidikiti</name>
<email>ramesh@wordnik.com</email>
</developer>
<developer>
<id>ayush</id>
<name>Ayush Gupta</name>
<email>ayush@glugbot.com</email>
</developer>
<developer>
<id>fehguy</id>
<name>Tony Tam</name>
<email>fehguy@gmail.com</email>
</developer>
<developer>
<id>casualjim</id>
<name>Ivan Porto Carrero</name>
<url>http://flanders.co.nz/</url>
</developer>
<developer>
<id>radius314</id>
<name>Danny Gershman</name>
<email>danny.gershman@gmail.com</email>
</developer>
</developers>
)}
assemblySettings
// jarName in assembly := "swagger-codegen.jar"

View File

@ -1 +0,0 @@
sbt.version=0.13.5

View File

@ -228,6 +228,7 @@ class APIClient {
$deserialized = $values;
} elseif (substr($class, 0, 6) == 'array[') {
$subClass = substr($class, 6, -1);
$values = array();
foreach ($data as $key => $value) {
$values[] = self::deserialize($value, $subClass);
}

652
samples/html/index.html Normal file
View File

@ -0,0 +1,652 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<title>API Reference</title>
<link rel="stylesheet" type="text/css" href="site.css" media="screen" />
</head>
<body>
<h1>Swagger Petstore</h1>
<div class="app-desc">This is a sample server Petstore server. You can find out more about Swagger at <a href="http://swagger.io">http://swagger.io</a> or on irc.freenode.net, #swagger. For this sample, you can use the api key "special-key" to test the authorization filters for our Partner</div>
<div class="app-desc">Contact Info: <a href="apiteam@wordnik.com">apiteam@wordnik.com</a></div>
<div class="license-info">Apache 2.0</div>
<div class="license-url">http://www.apache.org/licenses/LICENSE-2.0.html</div>
<h2>Access</h2>
<div class="method-summary">Access to the API requires an api key to be provided by our Partner for all requests. The api key is passed as a header with the name `api_key` and the value provided by Reverb Technologies, Inc. Unless otherwise agreed upon, access to the Reverb API is intended solely for usage by our Partner and not third parties.</div>
<h2>Methods</h2>
<div class="method">
<div class="method-path"><pre class="post"><code class="huge"><span>post</span>: /user</code></pre></div>
<div class="method-summary"><span class="nickname">createUser</span> Create user</div>
<div class="method-notes">This can only be done by the logged in user.</div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">body (optional)</div>
<div class="param-desc"><span class="param-type">Body Parameter</span> &mdash; Created user object </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="post"><code class="huge"><span>post</span>: /user/createWithArray</code></pre></div>
<div class="method-summary"><span class="nickname">createUsersWithArrayInput</span> Creates list of users with given input array</div>
<div class="method-notes"></div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">body (optional)</div>
<div class="param-desc"><span class="param-type">Body Parameter</span> &mdash; List of user object </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="post"><code class="huge"><span>post</span>: /user/createWithList</code></pre></div>
<div class="method-summary"><span class="nickname">createUsersWithListInput</span> Creates list of users with given input array</div>
<div class="method-notes"></div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">body (optional)</div>
<div class="param-desc"><span class="param-type">Body Parameter</span> &mdash; List of user object </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="get"><code class="huge"><span>get</span>: /user/login</code></pre></div>
<div class="method-summary"><span class="nickname">loginUser</span> Logs user into the system</div>
<div class="method-notes"></div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">username (optional)</div>
<div class="param-desc"><span class="param-type">Query Parameter</span> &mdash; The user name for login </div>
<div class="param">password (optional)</div>
<div class="param-desc"><span class="param-type">Query Parameter</span> &mdash; The password for login in clear text </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#">String</a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="get"><code class="huge"><span>get</span>: /user/logout</code></pre></div>
<div class="method-summary"><span class="nickname">logoutUser</span> Logs out current logged in user session</div>
<div class="method-notes"></div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="get"><code class="huge"><span>get</span>: /user/{username}</code></pre></div>
<div class="method-summary"><span class="nickname">getUserByName</span> Get user by user name</div>
<div class="method-notes"></div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">username (required)</div>
<div class="param-desc"><span class="param-type">Path Parameter</span> &mdash; The name that needs to be fetched. Use user1 for testing. </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#">User</a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="put"><code class="huge"><span>put</span>: /user/{username}</code></pre></div>
<div class="method-summary"><span class="nickname">updateUser</span> Updated user</div>
<div class="method-notes">This can only be done by the logged in user.</div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">username (required)</div>
<div class="param-desc"><span class="param-type">Path Parameter</span> &mdash; name that need to be deleted </div>
<div class="param">body (optional)</div>
<div class="param-desc"><span class="param-type">Body Parameter</span> &mdash; Updated user object </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="delete"><code class="huge"><span>delete</span>: /user/{username}</code></pre></div>
<div class="method-summary"><span class="nickname">deleteUser</span> Delete user</div>
<div class="method-notes">This can only be done by the logged in user.</div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">username (required)</div>
<div class="param-desc"><span class="param-type">Path Parameter</span> &mdash; The name that needs to be deleted </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="get"><code class="huge"><span>get</span>: /store/inventory</code></pre></div>
<div class="method-summary"><span class="nickname">getInventory</span> Returns pet inventories by status</div>
<div class="method-notes">Returns a map of status codes to quantities</div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#map">map[String, Integer]</a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="post"><code class="huge"><span>post</span>: /store/order</code></pre></div>
<div class="method-summary"><span class="nickname">placeOrder</span> Place an order for a pet</div>
<div class="method-notes"></div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">body (optional)</div>
<div class="param-desc"><span class="param-type">Body Parameter</span> &mdash; order placed for purchasing the pet </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#">Order</a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="get"><code class="huge"><span>get</span>: /store/order/{orderId}</code></pre></div>
<div class="method-summary"><span class="nickname">getOrderById</span> Find purchase order by ID</div>
<div class="method-notes">For valid response try integer IDs with value &lt;= 5 or &gt; 10. Other values will generated exceptions</div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">orderId (required)</div>
<div class="param-desc"><span class="param-type">Path Parameter</span> &mdash; ID of pet that needs to be fetched </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#">Order</a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="delete"><code class="huge"><span>delete</span>: /store/order/{orderId}</code></pre></div>
<div class="method-summary"><span class="nickname">deleteOrder</span> Delete purchase order by ID</div>
<div class="method-notes">For valid response try integer IDs with value &lt; 1000. Anything above 1000 or nonintegers will generate API errors</div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">orderId (required)</div>
<div class="param-desc"><span class="param-type">Path Parameter</span> &mdash; ID of the order that needs to be deleted </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="put"><code class="huge"><span>put</span>: /pet</code></pre></div>
<div class="method-summary"><span class="nickname">updatePet</span> Update an existing pet</div>
<div class="method-notes"></div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">body (optional)</div>
<div class="param-desc"><span class="param-type">Body Parameter</span> &mdash; Pet object that needs to be added to the store </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="post"><code class="huge"><span>post</span>: /pet</code></pre></div>
<div class="method-summary"><span class="nickname">addPet</span> Add a new pet to the store</div>
<div class="method-notes"></div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">body (optional)</div>
<div class="param-desc"><span class="param-type">Body Parameter</span> &mdash; Pet object that needs to be added to the store </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="get"><code class="huge"><span>get</span>: /pet/findByStatus</code></pre></div>
<div class="method-summary"><span class="nickname">findPetsByStatus</span> Finds Pets by status</div>
<div class="method-notes">Multiple status values can be provided with comma seperated strings</div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">status (optional)</div>
<div class="param-desc"><span class="param-type">Query Parameter</span> &mdash; Status values that need to be considered for filter </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#array">array[Pet]</a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="get"><code class="huge"><span>get</span>: /pet/findByTags</code></pre></div>
<div class="method-summary"><span class="nickname">findPetsByTags</span> Finds Pets by tags</div>
<div class="method-notes">Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.</div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">tags (optional)</div>
<div class="param-desc"><span class="param-type">Query Parameter</span> &mdash; Tags to filter by </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#array">array[Pet]</a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="get"><code class="huge"><span>get</span>: /pet/{petId}</code></pre></div>
<div class="method-summary"><span class="nickname">getPetById</span> Find pet by ID</div>
<div class="method-notes">Returns a pet when ID &lt; 10. ID &gt; 10 or nonintegers will simulate API error conditions</div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">petId (required)</div>
<div class="param-desc"><span class="param-type">Path Parameter</span> &mdash; ID of pet that needs to be fetched </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#">Pet</a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="post"><code class="huge"><span>post</span>: /pet/{petId}</code></pre></div>
<div class="method-summary"><span class="nickname">updatePetWithForm</span> Updates a pet in the store with form data</div>
<div class="method-notes"></div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">petId (required)</div>
<div class="param-desc"><span class="param-type">Path Parameter</span> &mdash; ID of pet that needs to be updated </div>
<div class="param">name (optional)</div>
<div class="param-desc"><span class="param-type">Form Parameter</span> &mdash; Updated name of the pet </div>
<div class="param">status (optional)</div>
<div class="param-desc"><span class="param-type">Form Parameter</span> &mdash; Updated status of the pet </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="delete"><code class="huge"><span>delete</span>: /pet/{petId}</code></pre></div>
<div class="method-summary"><span class="nickname">deletePet</span> Deletes a pet</div>
<div class="method-notes"></div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">api_key (optional)</div>
<div class="param-desc"><span class="param-type">Header Parameter</span> &mdash; </div>
<div class="param">petId (required)</div>
<div class="param-desc"><span class="param-type">Path Parameter</span> &mdash; Pet id to delete </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<div class="method">
<div class="method-path"><pre class="post"><code class="huge"><span>post</span>: /pet/{petId}/uploadImage</code></pre></div>
<div class="method-summary"><span class="nickname">uploadFile</span> uploads an image</div>
<div class="method-notes"></div>
<h3 class="field-label">Parameters</h3>
<div class="field-items">
<div class="param">petId (required)</div>
<div class="param-desc"><span class="param-type">Path Parameter</span> &mdash; ID of pet to update </div>
<div class="param">additionalMetadata (optional)</div>
<div class="param-desc"><span class="param-type">Form Parameter</span> &mdash; Additional data to pass to server </div>
<div class="param">file (optional)</div>
<div class="param-desc"><span class="param-type">Form Parameter</span> &mdash; file to upload </div>
</div> <!-- field-items -->
<h3 class="field-label">Return type</h3>
<div class="return-type"><a href="#"></a></div>
</div> <!-- method -->
<hr>
<h2>Models</h2>
<div class="model">
<h3 class="field-label"><a name="User">User</a></h3>
<div class="field-items">
<div class="param">id </div><div class="param-desc"><span class="param-type">Long</span> </div>
<div class="param">username </div><div class="param-desc"><span class="param-type">String</span> </div>
<div class="param">firstName </div><div class="param-desc"><span class="param-type">String</span> </div>
<div class="param">lastName </div><div class="param-desc"><span class="param-type">String</span> </div>
<div class="param">email </div><div class="param-desc"><span class="param-type">String</span> </div>
<div class="param">password </div><div class="param-desc"><span class="param-type">String</span> </div>
<div class="param">phone </div><div class="param-desc"><span class="param-type">String</span> </div>
<div class="param">userStatus </div><div class="param-desc"><span class="param-type">Integer</span> User Status</div>
</div> <!-- field-items -->
</div>
<div class="model">
<h3 class="field-label"><a name="Category">Category</a></h3>
<div class="field-items">
<div class="param">id </div><div class="param-desc"><span class="param-type">Long</span> </div>
<div class="param">name </div><div class="param-desc"><span class="param-type">String</span> </div>
</div> <!-- field-items -->
</div>
<div class="model">
<h3 class="field-label"><a name="Pet">Pet</a></h3>
<div class="field-items">
<div class="param">id </div><div class="param-desc"><span class="param-type">Long</span> </div>
<div class="param">category </div><div class="param-desc"><span class="param-type">Category</span> </div>
<div class="param">name </div><div class="param-desc"><span class="param-type">String</span> </div>
<div class="param">photoUrls </div><div class="param-desc"><span class="param-type">array[String]</span> </div>
<div class="param">tags </div><div class="param-desc"><span class="param-type">array[Tag]</span> </div>
<div class="param">status </div><div class="param-desc"><span class="param-type">String</span> pet status in the store</div>
</div> <!-- field-items -->
</div>
<div class="model">
<h3 class="field-label"><a name="Tag">Tag</a></h3>
<div class="field-items">
<div class="param">id </div><div class="param-desc"><span class="param-type">Long</span> </div>
<div class="param">name </div><div class="param-desc"><span class="param-type">String</span> </div>
</div> <!-- field-items -->
</div>
<div class="model">
<h3 class="field-label"><a name="Order">Order</a></h3>
<div class="field-items">
<div class="param">id </div><div class="param-desc"><span class="param-type">Long</span> </div>
<div class="param">petId </div><div class="param-desc"><span class="param-type">Long</span> </div>
<div class="param">quantity </div><div class="param-desc"><span class="param-type">Integer</span> </div>
<div class="param">shipDate </div><div class="param-desc"><span class="param-type">Date</span> </div>
<div class="param">status </div><div class="param-desc"><span class="param-type">String</span> Order Status</div>
<div class="param">complete </div><div class="param-desc"><span class="param-type">Boolean</span> </div>
</div> <!-- field-items -->
</div>
<style>
body {
font-family: Trebuchet MS, sans-serif;
font-size: 15px;
color: #444;
margin-right: 24px;
}
h1 {
font-size: 25px;
}
h2 {
font-size: 20px;
}
h3 {
font-size: 16px;
font-weight: bold;
}
hr {
height: 1px;
border: 0;
color: #ddd;
background-color: #ddd;
display: none;
}
.app-desc {
clear: both;
margin-left: 20px;
}
.param-name {
width: 100%;
}
.license-info {
margin-left: 20px;
}
.license-url {
margin-left: 20px;
}
.model {
margin: 0 0 0px 20px;
}
.method {
margin-left: 20px;
}
.method-notes {
margin: 10px 0 20px 0;
font-size: 90%;
color: #555;
}
pre {
padding: 10px;
}
pre.get {
background-color: #0f6ab4;
}
pre.post {
background-color: #10a54a;
}
pre.put {
background-color: #c5862b;
}
pre.delete {
background-color: #a41e22;
}
.huge {
color: #fff;
}
pre.example {
background-color: #f3f3f3;
padding: 10px;
border: 1px solid #ddd;
}
code {
white-space: pre;
}
.nickname {
font-weight: bold;
}
.method-path {
font-size: 1.5em;
background-color: #0f6ab4;
}
.parameter {
width: 500px;
}
.param {
width: 500px;
padding: 10px 0 0 20px;
font-weight: bold;
}
.param-desc {
width: 700px;
padding: 0 0 0 20px;
color: #777;
}
.param-type {
font-style: italic;
}
.field-label {
padding: 0;
margin: 0;
clear: both;
}
.field-items {
padding: 0 0 15px 0;
margin-bottom: 15px;
}
.return-type {
clear: both;
padding-bottom: 10px;
}
.param-header {
font-weight: bold;
}
</style>
</body>
</html>

518
sbt
View File

@ -1,518 +0,0 @@
#!/usr/bin/env bash
#
# A more capable sbt runner, coincidentally also called sbt.
# Author: Paul Phillips <paulp@typesafe.com>
# todo - make this dynamic
declare -r sbt_release_version=0.12.4
declare -r sbt_beta_version=0.13.0-RC4
declare -r sbt_snapshot_version=0.13.0-SNAPSHOT
declare sbt_jar sbt_dir sbt_create sbt_snapshot sbt_launch_dir
declare scala_version java_home sbt_explicit_version
declare verbose debug quiet noshare batch trace_level log_level
declare sbt_saved_stty
echoerr () { [[ -z $quiet ]] && echo "$@" >&2; }
vlog () { [[ -n "$verbose$debug" ]] && echoerr "$@"; }
dlog () { [[ -n $debug ]] && echoerr "$@"; }
# we'd like these set before we get around to properly processing arguments
for arg in "$@"; do
case $arg in
-q|-quiet) quiet=true ;;
-d|-debug) debug=true ;;
-v|-verbose) verbose=true ;;
*) ;;
esac
done
build_props_sbt () {
if [[ -r project/build.properties ]]; then
versionLine=$(grep ^sbt.version project/build.properties | tr -d '\r')
versionString=${versionLine##sbt.version=}
echo "$versionString"
fi
}
update_build_props_sbt () {
local ver="$1"
local old=$(build_props_sbt)
if [[ $ver == $old ]]; then
return
elif [[ -r project/build.properties ]]; then
perl -pi -e "s/^sbt\.version=.*\$/sbt.version=${ver}/" project/build.properties
grep -q '^sbt.version=' project/build.properties || echo "sbt.version=${ver}" >> project/build.properties
echoerr !!!
echoerr !!! Updated file project/build.properties setting sbt.version to: $ver
echoerr !!! Previous value was: $old
echoerr !!!
fi
}
sbt_version () {
if [[ -n $sbt_explicit_version ]]; then
echo $sbt_explicit_version
else
local v=$(build_props_sbt)
if [[ -n $v ]]; then
echo $v
else
echo $sbt_release_version
fi
fi
}
# restore stty settings (echo in particular)
onSbtRunnerExit() {
[[ -n $sbt_saved_stty ]] || return
dlog ""
dlog "restoring stty: $sbt_saved_stty"
stty $sbt_saved_stty
unset sbt_saved_stty
}
# save stty and trap exit, to ensure echo is reenabled if we are interrupted.
trap onSbtRunnerExit EXIT
sbt_saved_stty=$(stty -g 2>/dev/null)
dlog "Saved stty: $sbt_saved_stty"
# this seems to cover the bases on OSX, and someone will
# have to tell me about the others.
get_script_path () {
local path="$1"
[[ -L "$path" ]] || { echo "$path" ; return; }
local target=$(readlink "$path")
if [[ "${target:0:1}" == "/" ]]; then
echo "$target"
else
echo "$(dirname $path)/$target"
fi
}
die() {
echo "Aborting: $@"
exit 1
}
make_url () {
groupid="$1"
category="$2"
version="$3"
echo "http://typesafe.artifactoryonline.com/typesafe/ivy-$category/$groupid/sbt-launch/$version/sbt-launch.jar"
}
readarr () {
while read ; do
eval "$1+=(\"$REPLY\")"
done
}
init_default_option_file () {
local overriding_var=${!1}
local default_file=$2
if [[ ! -r "$default_file" && $overriding_var =~ ^@(.*)$ ]]; then
local envvar_file=${BASH_REMATCH[1]}
if [[ -r $envvar_file ]]; then
default_file=$envvar_file
fi
fi
echo $default_file
}
declare -r default_jvm_opts="-Dfile.encoding=UTF8 -XX:MaxPermSize=256m -Xms512m -Xmx1g -XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC"
declare -r noshare_opts="-Dsbt.global.base=project/.sbtboot -Dsbt.boot.directory=project/.boot -Dsbt.ivy.home=project/.ivy"
declare -r latest_28="2.8.2"
declare -r latest_29="2.9.3"
declare -r latest_210="2.10.4"
declare -r script_path=$(get_script_path "$BASH_SOURCE")
declare -r script_dir="$(dirname $script_path)"
declare -r script_name="$(basename $script_path)"
# some non-read-onlies set with defaults
declare java_cmd=java
declare sbt_opts_file=$(init_default_option_file SBT_OPTS .sbtopts)
declare jvm_opts_file=$(init_default_option_file JVM_OPTS .jvmopts)
# pull -J and -D options to give to java.
declare -a residual_args
declare -a java_args
declare -a scalac_args
declare -a sbt_commands
# args to jvm/sbt via files or environment variables
declare -a extra_jvm_opts extra_sbt_opts
# if set, use JAVA_HOME over java found in path
[[ -e "$JAVA_HOME/bin/java" ]] && java_cmd="$JAVA_HOME/bin/java"
# directory to store sbt launchers
declare sbt_launch_dir="$HOME/.sbt/launchers"
[[ -d "$sbt_launch_dir" ]] || mkdir -p "$sbt_launch_dir"
[[ -w "$sbt_launch_dir" ]] || sbt_launch_dir="$(mktemp -d -t sbt_extras_launchers)"
build_props_scala () {
if [[ -r project/build.properties ]]; then
versionLine=$(grep ^build.scala.versions project/build.properties)
versionString=${versionLine##build.scala.versions=}
echo ${versionString%% .*}
fi
}
execRunner () {
# print the arguments one to a line, quoting any containing spaces
[[ $verbose || $debug ]] && echo "# Executing command line:" && {
for arg; do
if [[ -n "$arg" ]]; then
if printf "%s\n" "$arg" | grep -q ' '; then
printf "\"%s\"\n" "$arg"
else
printf "%s\n" "$arg"
fi
fi
done
echo ""
}
if [[ -n $batch ]]; then
# the only effective way I've found to avoid sbt hanging when backgrounded.
exec 0<&-
( "$@" & )
# I'm sure there's some way to get our hands on the pid and wait for it
# but it exceeds my present level of ambition.
else
{ "$@"; }
fi
}
sbt_groupid () {
case $(sbt_version) in
0.7.*) echo org.scala-tools.sbt ;;
0.10.*) echo org.scala-tools.sbt ;;
0.11.[12]) echo org.scala-tools.sbt ;;
*) echo org.scala-sbt ;;
esac
}
sbt_artifactory_list () {
local version0=$(sbt_version)
local version=${version0%-SNAPSHOT}
local url="http://typesafe.artifactoryonline.com/typesafe/ivy-snapshots/$(sbt_groupid)/sbt-launch/"
dlog "Looking for snapshot list at: $url "
curl -s --list-only "$url" | \
grep -F $version | \
perl -e 'print reverse <>' | \
perl -pe 's#^<a href="([^"/]+).*#$1#;'
}
make_release_url () {
make_url $(sbt_groupid) releases $(sbt_version)
}
# argument is e.g. 0.13.0-SNAPSHOT
# finds the actual version (with the build id) at artifactory
make_snapshot_url () {
for ver in $(sbt_artifactory_list); do
local url=$(make_url $(sbt_groupid) snapshots $ver)
dlog "Testing $url"
curl -s --head "$url" >/dev/null
dlog "curl returned: $?"
echo "$url"
return
done
}
jar_url () {
case $(sbt_version) in
0.7.*) echo "http://simple-build-tool.googlecode.com/files/sbt-launch-0.7.7.jar" ;;
*-SNAPSHOT) make_snapshot_url ;;
*) make_release_url ;;
esac
}
jar_file () {
case $1 in
0.13.*) echo "$sbt_launch_dir/$1/sbt-launch.jar" ;;
*) echo "$sbt_launch_dir/$sbt_release_version/sbt-launch.jar" ;;
esac
}
download_url () {
local url="$1"
local jar="$2"
echo "Downloading sbt launcher $(sbt_version):"
echo " From $url"
echo " To $jar"
mkdir -p $(dirname "$jar") && {
if which curl >/dev/null; then
curl --fail --silent "$url" --output "$jar"
elif which wget >/dev/null; then
wget --quiet -O "$jar" "$url"
fi
} && [[ -r "$jar" ]]
}
acquire_sbt_jar () {
sbt_url="$(jar_url)"
sbt_jar="$(jar_file $(sbt_version))"
[[ -r "$sbt_jar" ]] || download_url "$sbt_url" "$sbt_jar"
}
usage () {
cat <<EOM
Usage: $script_name [options]
-h | -help print this message
-v | -verbose this runner is chattier
-d | -debug set sbt log level to Debug
-q | -quiet set sbt log level to Error
-trace <level> display stack traces with a max of <level> frames (default: -1, traces suppressed)
-no-colors disable ANSI color codes
-sbt-create start sbt even if current directory contains no sbt project
-sbt-dir <path> path to global settings/plugins directory (default: ~/.sbt/<version>)
-sbt-boot <path> path to shared boot directory (default: ~/.sbt/boot in 0.11+)
-ivy <path> path to local Ivy repository (default: ~/.ivy2)
-no-share use all local caches; no sharing
-offline put sbt in offline mode
-jvm-debug <port> Turn on JVM debugging, open at the given port.
-batch Disable interactive mode
-prompt <expr> Set the sbt prompt; in expr, 's' is the State and 'e' is Extracted
# sbt version (default: from project/build.properties if present, else latest release)
!!! The only way to accomplish this pre-0.12.0 if there is a build.properties file which
!!! contains an sbt.version property is to update the file on disk. That's what this does.
-sbt-version <version> use the specified version of sbt (default: $sbt_release_version)
-sbt-jar <path> use the specified jar as the sbt launcher
-sbt-beta use a beta version of sbt (currently: $sbt_beta_version)
-sbt-snapshot use a snapshot version of sbt (currently: $sbt_snapshot_version)
-sbt-launch-dir <path> directory to hold sbt launchers (default: $sbt_launch_dir)
# scala version (default: as chosen by sbt)
-28 use $latest_28
-29 use $latest_29
-210 use $latest_210
-scala-home <path> use the scala build at the specified directory
-scala-version <version> use the specified version of scala
-binary-version <version> use the specified scala version when searching for dependencies
# java version (default: java from PATH, currently $(java -version 2>&1 | grep version))
-java-home <path> alternate JAVA_HOME
# passing options to the jvm - note it does NOT use JAVA_OPTS due to pollution
# The default set is used if JVM_OPTS is unset and no -jvm-opts file is found
<default> $default_jvm_opts
JVM_OPTS environment variable holding either the jvm args directly, or
the reference to a file containing jvm args if given path is prepended by '@' (e.g. '@/etc/jvmopts')
Note: "@"-file is overridden by local '.jvmopts' or '-jvm-opts' argument.
-jvm-opts <path> file containing jvm args (if not given, .jvmopts in project root is used if present)
-Dkey=val pass -Dkey=val directly to the jvm
-J-X pass option -X directly to the jvm (-J is stripped)
# passing options to sbt, OR to this runner
SBT_OPTS environment variable holding either the sbt args directly, or
the reference to a file containing sbt args if given path is prepended by '@' (e.g. '@/etc/sbtopts')
Note: "@"-file is overridden by local '.sbtopts' or '-sbt-opts' argument.
-sbt-opts <path> file containing sbt args (if not given, .sbtopts in project root is used if present)
-S-X add -X to sbt's scalacOptions (-S is stripped)
EOM
}
addJava () {
dlog "[addJava] arg = '$1'"
java_args=( "${java_args[@]}" "$1" )
}
addSbt () {
dlog "[addSbt] arg = '$1'"
sbt_commands=( "${sbt_commands[@]}" "$1" )
}
addScalac () {
dlog "[addScalac] arg = '$1'"
scalac_args=( "${scalac_args[@]}" "$1" )
}
addResidual () {
dlog "[residual] arg = '$1'"
residual_args=( "${residual_args[@]}" "$1" )
}
addResolver () {
addSbt "set resolvers in ThisBuild += $1"
}
addDebugger () {
addJava "-Xdebug"
addJava "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=$1"
}
setScalaVersion () {
addSbt "set scalaVersion in ThisBuild := \"$1\""
if [[ "$1" == *SNAPSHOT* ]]; then
addResolver Opts.resolver.sonatypeSnapshots
fi
}
process_args ()
{
require_arg () {
local type="$1"
local opt="$2"
local arg="$3"
if [[ -z "$arg" ]] || [[ "${arg:0:1}" == "-" ]]; then
die "$opt requires <$type> argument"
fi
}
while [[ $# -gt 0 ]]; do
case "$1" in
-h|-help) usage; exit 1 ;;
-v|-verbose) verbose=true && log_level=Info && shift ;;
-d|-debug) debug=true && log_level=Debug && shift ;;
-q|-quiet) quiet=true && log_level=Error && shift ;;
-trace) require_arg integer "$1" "$2" && trace_level=$2 && shift 2 ;;
-ivy) require_arg path "$1" "$2" && addJava "-Dsbt.ivy.home=$2" && shift 2 ;;
-no-colors) addJava "-Dsbt.log.noformat=true" && shift ;;
-no-share) noshare=true && shift ;;
-sbt-boot) require_arg path "$1" "$2" && addJava "-Dsbt.boot.directory=$2" && shift 2 ;;
-sbt-dir) require_arg path "$1" "$2" && sbt_dir="$2" && shift 2 ;;
-debug-inc) addJava "-Dxsbt.inc.debug=true" && shift ;;
-offline) addSbt "set offline := true" && shift ;;
-jvm-debug) require_arg port "$1" "$2" && addDebugger $2 && shift 2 ;;
-batch) batch=true && shift ;;
-prompt) require_arg "expr" "$1" "$2" && addSbt "set shellPrompt in ThisBuild := (s => { val e = Project.extract(s) ; $2 })" && shift 2 ;;
-sbt-create) sbt_create=true && shift ;;
-sbt-snapshot) sbt_explicit_version=$sbt_snapshot_version && shift ;;
-sbt-beta) sbt_explicit_version=$sbt_beta_version && shift ;;
-sbt-jar) require_arg path "$1" "$2" && sbt_jar="$2" && shift 2 ;;
-sbt-version) require_arg version "$1" "$2" && sbt_explicit_version="$2" && shift 2 ;;
-sbt-launch-dir) require_arg path "$1" "$2" && sbt_launch_dir="$2" && shift 2 ;;
-scala-version) require_arg version "$1" "$2" && setScalaVersion "$2" && shift 2 ;;
-binary-version) require_arg version "$1" "$2" && addSbt "set scalaBinaryVersion in ThisBuild := \"$2\"" && shift 2 ;;
-scala-home) require_arg path "$1" "$2" && addSbt "set every scalaHome := Some(file(\"$2\"))" && shift 2 ;;
-java-home) require_arg path "$1" "$2" && java_cmd="$2/bin/java" && shift 2 ;;
-sbt-opts) require_arg path "$1" "$2" && sbt_opts_file="$2" && shift 2 ;;
-jvm-opts) require_arg path "$1" "$2" && jvm_opts_file="$2" && shift 2 ;;
-D*) addJava "$1" && shift ;;
-J*) addJava "${1:2}" && shift ;;
-S*) addScalac "${1:2}" && shift ;;
-28) addSbt "++ $latest_28" && shift ;;
-29) addSbt "++ $latest_29" && shift ;;
-210) addSbt "++ $latest_210" && shift ;;
*) addResidual "$1" && shift ;;
esac
done
}
# process the direct command line arguments
process_args "$@"
# skip #-styled comments
readConfigFile() {
while read line; do echo ${line/\#*/} | grep -vE '^\s*$'; done < $1
}
# if there are file/environment sbt_opts, process again so we
# can supply args to this runner
if [[ -r "$sbt_opts_file" ]]; then
vlog "Using sbt options defined in file $sbt_opts_file"
readarr extra_sbt_opts < <(readConfigFile "$sbt_opts_file")
elif [[ -n "$SBT_OPTS" && !($SBT_OPTS =~ ^@.*) ]]; then
vlog "Using sbt options defined in variable \$SBT_OPTS"
extra_sbt_opts=( $SBT_OPTS )
else
vlog "No extra sbt options have been defined"
fi
[[ -n $extra_sbt_opts ]] && process_args "${extra_sbt_opts[@]}"
# reset "$@" to the residual args
set -- "${residual_args[@]}"
argumentCount=$#
# only exists in 0.12+
setTraceLevel() {
case $(sbt_version) in
0.{7,10,11}.*) echoerr "Cannot set trace level in sbt version $(sbt_version)" ;;
*) addSbt "set every traceLevel := $trace_level" ;;
esac
}
# set scalacOptions if we were given any -S opts
[[ ${#scalac_args[@]} -eq 0 ]] || addSbt "set scalacOptions in ThisBuild += \"${scalac_args[@]}\""
# Update build.properties no disk to set explicit version - sbt gives us no choice
[[ -n "$sbt_explicit_version" ]] && update_build_props_sbt "$sbt_explicit_version"
vlog "Detected sbt version $(sbt_version)"
[[ -n "$scala_version" ]] && echoerr "Overriding scala version to $scala_version"
# no args - alert them there's stuff in here
(( $argumentCount > 0 )) || vlog "Starting $script_name: invoke with -help for other options"
# verify this is an sbt dir or -create was given
[[ -r ./build.sbt || -d ./project || -n "$sbt_create" ]] || {
cat <<EOM
$(pwd) doesn't appear to be an sbt project.
If you want to start sbt anyway, run:
$0 -sbt-create
EOM
exit 1
}
# pick up completion if present; todo
[[ -r .sbt_completion.sh ]] && source .sbt_completion.sh
# no jar? download it.
[[ -r "$sbt_jar" ]] || acquire_sbt_jar || {
# still no jar? uh-oh.
echo "Download failed. Obtain the jar manually and place it at $sbt_jar"
exit 1
}
if [[ -n $noshare ]]; then
addJava "$noshare_opts"
else
[[ -n "$sbt_dir" ]] || {
sbt_dir=~/.sbt/$(sbt_version)
vlog "Using $sbt_dir as sbt dir, -sbt-dir to override."
}
addJava "-Dsbt.global.base=$sbt_dir"
fi
if [[ -r "$jvm_opts_file" ]]; then
vlog "Using jvm options defined in file $jvm_opts_file"
readarr extra_jvm_opts < <(readConfigFile "$jvm_opts_file")
elif [[ -n "$JVM_OPTS" && !($JVM_OPTS =~ ^@.*) ]]; then
vlog "Using jvm options defined in \$JVM_OPTS variable"
extra_jvm_opts=( $JVM_OPTS )
else
vlog "Using default jvm options"
extra_jvm_opts=( $default_jvm_opts )
fi
# since sbt 0.7 doesn't understand iflast
[[ ${#residual_args[@]} -eq 0 ]] && [[ -z "$batch" ]] && residual_args=( "shell" )
# traceLevel is 0.12+
[[ -n $trace_level ]] && setTraceLevel
[[ -n $log_level ]] && [[ $log_level != Info ]] && logLevalArg="set logLevel in Global := Level.$log_level"
# run sbt
execRunner "$java_cmd" \
"${extra_jvm_opts[@]}" \
"${java_args[@]}" \
-jar "$sbt_jar" \
"$logLevalArg" \
"${sbt_commands[@]}" \
"${residual_args[@]}"

View File

@ -1,31 +0,0 @@
val wordnikSnapshots = "Wordnik Snapshots" at "https://ci.aws.wordnik.com/artifactory/m2-snapshots/"
val wordnikReleases = "Wordnik Releases" at "https://ci.aws.wordnik.com/artifactory/m2-releases/"
val wordnikRemoteRepos = "Wordnik Remote Repos" at "https://ci.aws.wordnik.com/artifactory/remote-repos/"
scalaVersion := "2.11.2"
crossScalaVersions := Seq("2.10.4", "2.11.2")
scalacOptions ++= Seq("-unchecked", "-deprecation", "-optimize", "-Xcheckinit", "-encoding", "utf8")
version := "1.6.1"
publishTo <<= (version) { version: String =>
val artifactory = "https://ci.aws.wordnik.com/artifactory/m2-"
if (version.trim.endsWith("SNAPSHOT"))
Some("snapshots" at artifactory + "snapshots")
else
Some("releases" at artifactory + "releases")
}
publishMavenStyle := true
publishArtifact in Test := false
pomIncludeRepository := { x => false }
credentials += Credentials("Artifactory Realm", "ci.aws.wordnik.com", "mavenuser", "DEEaffe987a")
resolvers ++= Seq(wordnikSnapshots, wordnikReleases, wordnikRemoteRepos)

View File

@ -1,239 +0,0 @@
{{#operations}}
#import "{{classname}}.h"
#import "SWGFile.h"
#import "SWGApiClient.h"
{{#imports}}#import "{{import}}.h"
{{/imports}}
{{newline}}
@implementation {{classname}}
static NSString * basePath = @"{{basePath}}";
+({{classname}}*) apiWithHeader:(NSString*)headerValue key:(NSString*)key {
static {{classname}}* singletonAPI = nil;
if (singletonAPI == nil) {
singletonAPI = [[{{classname}} alloc] init];
[singletonAPI addHeader:headerValue forKey:key];
}
return singletonAPI;
}
+(void) setBasePath:(NSString*)path {
basePath = path;
}
+(NSString*) getBasePath {
return basePath;
}
-(SWGApiClient*) apiClient {
return [SWGApiClient sharedClientFromPool:basePath];
}
-(void) addHeader:(NSString*)value forKey:(NSString*)key {
[[self apiClient] setHeaderValue:value forKey:key];
}
-(id) init {
self = [super init];
[self apiClient];
return self;
}
-(void) setHeaderValue:(NSString*) value
forKey:(NSString*)key {
[[self apiClient] setHeaderValue:value forKey:key];
}
-(unsigned long) requestQueueSize {
return [SWGApiClient requestQueueSize];
}
{{#operation}}
-(NSNumber*) {{nickname}}WithCompletionBlock{{^allParams}}: {{/allParams}}{{#allParams}}{{#secondaryParam}} {{paramName}}{{/secondaryParam}}:({{{dataType}}}) {{paramName}}{{newline}} {{/allParams}}
{{#returnBaseType}}{{#hasParams}}completionHandler : {{/hasParams}}(void (^)({{returnType}} output, NSError* error))completionBlock{{/returnBaseType}}
{{^returnBaseType}}{{#hasParams}}completionHandler : {{/hasParams}}(void (^)(NSError* error))completionBlock{{/returnBaseType}} {
NSMutableString* requestUrl = [NSMutableString stringWithFormat:@"%@{{path}}", basePath];
// remove format in URL if needed
if ([requestUrl rangeOfString:@".{format}"].location != NSNotFound)
[requestUrl replaceCharactersInRange: [requestUrl rangeOfString:@".{format}"] withString:@".json"];
{{#pathParams}}[requestUrl replaceCharactersInRange: [requestUrl rangeOfString:[NSString stringWithFormat:@"%@%@%@", @"{", @"{{baseName}}", @"}"]] withString: [SWGApiClient escape:{{paramName}}]];
{{/pathParams}}
NSString* requestContentType = @"application/json";
NSString* responseContentType = @"application/json";
NSMutableDictionary* queryParams = [[NSMutableDictionary alloc] init];
{{#queryParams}}if({{paramName}} != nil)
queryParams[@"{{baseName}}"] = {{paramName}};
{{/queryParams}}
NSMutableDictionary* headerParams = [[NSMutableDictionary alloc] init];
{{#headerParams}}if({{paramName}} != nil)
headerParams[@"{{baseName}}"] = {{paramName}};
{{/headerParams}}
id bodyDictionary = nil;
{{#bodyParam}}
if(body != nil && [body isKindOfClass:[NSArray class]]){
NSMutableArray * objs = [[NSMutableArray alloc] init];
for (id dict in (NSArray*)body) {
if([dict respondsToSelector:@selector(asDictionary)]) {
[objs addObject:[(SWGObject*)dict asDictionary]];
}
else{
[objs addObject:dict];
}
}
bodyDictionary = objs;
}
else if([body respondsToSelector:@selector(asDictionary)]) {
bodyDictionary = [(SWGObject*)body asDictionary];
}
else if([body isKindOfClass:[NSString class]]) {
// convert it to a dictionary
NSError * error;
NSString * str = (NSString*)body;
NSDictionary *JSON =
[NSJSONSerialization JSONObjectWithData:[str dataUsingEncoding:NSUTF8StringEncoding]
options:NSJSONReadingMutableContainers
error:&error];
bodyDictionary = JSON;
}
else if([body isKindOfClass: [SWGFile class]]) {
requestContentType = @"form-data";
bodyDictionary = body;
}
else{
NSLog(@"don't know what to do with %@", body);
}
{{/bodyParam}}
{{#requiredParamCount}}
{{#requiredParams}}
if({{paramName}} == nil) {
// error
}
{{/requiredParams}}
{{/requiredParamCount}}
SWGApiClient* client = [SWGApiClient sharedClientFromPool:basePath];
{{#returnContainer}}
return [client dictionary: requestUrl
method: @"{{httpMethod}}"
queryParams: queryParams
body: bodyDictionary
headerParams: headerParams
requestContentType: requestContentType
responseContentType: responseContentType
completionBlock: ^(NSDictionary *data, NSError *error) {
if (error) {
{{#returnBaseType}}completionBlock(nil, error);{{/returnBaseType}}
{{^returnBaseType}}completionBlock(error);{{/returnBaseType}}
return;
}
{{#returnBaseType}}
if([data isKindOfClass:[NSArray class]]){
NSMutableArray * objs = [[NSMutableArray alloc] initWithCapacity:[data count]];
for (NSDictionary* dict in (NSArray*)data) {
{{#returnTypeIsPrimitive}}
// {{#instantiationType}}NSClassFromString(@"{{{instantiationType}}}"){{/instantiationType}}{{^instantiationType}}{{{returnBaseType}}}{{/instantiationType}}{{newline}}
{{returnBaseType}}* d = [[{{#instantiationType}}NSClassFromString(@"{{{instantiationType}}}") {{/instantiationType}}{{^instantiationType}}{{{returnBaseType}}} {{/instantiationType}} alloc]initWithString: data];
{{/returnTypeIsPrimitive}}
{{^returnTypeIsPrimitive}}
{{{returnBaseType}}}* d = [[{{#instantiationType}}NSClassFromString(@"{{{instantiationType}}}") {{/instantiationType}}{{^instantiationType}}{{{returnBaseType}}} {{/instantiationType}} alloc]initWithValues: dict];
{{/returnTypeIsPrimitive}}
[objs addObject:d];
}
completionBlock(objs, nil);
}
{{#returnSimpleType}}
{{#returnTypeIsPrimitive}}{{#returnBaseType}}completionBlock( [[{{#instantiationType}}NSClassFromString(@"{{{instantiationType}}}") {{/instantiationType}}{{^instantiationType}}{{{returnBaseType}}} {{/instantiationType}} alloc]initWithString: data], nil;{{/returnBaseType}}
{{/returnTypeIsPrimitive}}
{{^returnTypeIsPrimitive}}
{{#returnBaseType}}completionBlock( [[{{#instantiationType}}NSClassFromString(@"{{{instantiationType}}}") {{/instantiationType}}{{^instantiationType}}{{{returnBaseType}}} {{/instantiationType}} alloc]initWithValues: data], nil);{{/returnBaseType}}
{{/returnTypeIsPrimitive}}
{{/returnSimpleType}}
{{/returnBaseType}}
}];
{{/returnContainer}}
{{#returnSimpleType}}
{{#returnTypeIsPrimitive}}
{{#returnBaseType}}
return [client stringWithCompletionBlock:requestUrl
method:@"{{httpMethod}}"
queryParams:queryParams
body:bodyDictionary
headerParams:headerParams
requestContentType: requestContentType
responseContentType: responseContentType
completionBlock:^(NSString *data, NSError *error) {
if (error) {
completionBlock(nil, error);
return;
}
{{returnBaseType}} *result = data ? [[{{#instantiationType}}NSClassFromString(@"{{{instantiationType}}}") {{/instantiationType}}{{^instantiationType}}{{{returnBaseType}}} {{/instantiationType}} alloc]initWithString: data] : nil;
completionBlock(result, nil);
}];
{{/returnBaseType}}
{{^returnBaseType}}
return [client stringWithCompletionBlock:requestUrl
method:@"{{httpMethod}}"
queryParams:queryParams
body:bodyDictionary
headerParams:headerParams
requestContentType: requestContentType
responseContentType: responseContentType
completionBlock:^(NSString *data, NSError *error) {
if (error) {
completionBlock(error);
return;
}
completionBlock(nil);
}];
{{/returnBaseType}}
{{/returnTypeIsPrimitive}}
{{#returnBaseType}}
{{^returnTypeIsPrimitive}}
return [client dictionary:requestUrl
method:@"{{httpMethod}}"
queryParams:queryParams
body:bodyDictionary
headerParams:headerParams
requestContentType:requestContentType
responseContentType:responseContentType
completionBlock:^(NSDictionary *data, NSError *error) {
if (error) {
{{#returnBaseType}}completionBlock(nil, error);{{/returnBaseType}}
{{^returnBaseType}}completionBlock(error);{{/returnBaseType}}
return;
}
{{#returnBaseType}}
{{returnBaseType}} *result = nil;
if (data) {
result = [[{{#instantiationType}}NSClassFromString(@"{{{instantiationType}}}") {{/instantiationType}}{{^instantiationType}}{{{returnBaseType}}} {{/instantiationType}} alloc]initWithValues: data];
}
{{#returnBaseType}}completionBlock(result , nil);{{/returnBaseType}}
{{/returnBaseType}}
}];
{{/returnTypeIsPrimitive}}
{{/returnBaseType}}
{{/returnSimpleType}}
{{newline}}
}
{{/operation}}
{{newline}}
{{/operations}}
@end

View File

@ -1,239 +0,0 @@
<?php
/**
* APIClient.php
*/
/* Autoload the model definition files */
/**
*
*
* @param string $className the class to attempt to load
*/
function swagger_autoloader($className) {
$currentDir = dirname(__FILE__);
if (file_exists($currentDir . '/' . $className . '.php')) {
include $currentDir . '/' . $className . '.php';
} elseif (file_exists($currentDir . '/models/' . $className . '.php')) {
include $currentDir . '/models/' . $className . '.php';
}
}
spl_autoload_register('swagger_autoloader');
class APIClient {
public static $POST = "POST";
public static $GET = "GET";
public static $PUT = "PUT";
public static $DELETE = "DELETE";
private $curl_timout = 5;
/**
* @param string $apiKey your API key
* @param string $apiServer the address of the API server
*/
function __construct($apiKey, $apiServer) {
$this->apiKey = $apiKey;
$this->apiServer = $apiServer;
}
/**
* @param integer $seconds Number of seconds before timing out [set to 0 for no timeout]
*/
public function setTimeout($seconds) {
if (!is_numeric($seconds)) {
throw new Exception('Timeout variable must be numeric.');
}
$this->curl_timout = $seconds;
}
/**
* @param string $resourcePath path to method endpoint
* @param string $method method to call
* @param array $queryParams parameters to be place in query URL
* @param array $postData parameters to be placed in POST body
* @param array $headerParams parameters to be place in request header
* @return mixed
*/
public function callAPI($resourcePath, $method, $queryParams, $postData,
$headerParams) {
$headers = array();
# Allow API key from $headerParams to override default
$added_api_key = False;
if ($headerParams != null) {
foreach ($headerParams as $key => $val) {
$headers[] = "$key: $val";
if ($key == 'api_key') {
$added_api_key = True;
}
}
}
if (! $added_api_key) {
$headers[] = "api_key: " . $this->apiKey;
}
if (strpos($headers['Content-Type'], "multipart/form-data") < 0 and (is_object($postData) or is_array($postData))) {
$postData = json_encode($this->sanitizeForSerialization($postData));
}
$url = $this->apiServer . $resourcePath;
$curl = curl_init();
if ($this->curl_timout) {
curl_setopt($curl, CURLOPT_TIMEOUT, $this->curl_timout);
}
// return the result on success, rather than just TRUE
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
if (! empty($queryParams)) {
$url = ($url . '?' . http_build_query($queryParams));
}
if ($method == self::$POST) {
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method == self::$PUT) {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "PUT");
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method == self::$DELETE) {
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "DELETE");
curl_setopt($curl, CURLOPT_POSTFIELDS, $postData);
} else if ($method != self::$GET) {
throw new Exception('Method ' . $method . ' is not recognized.');
}
curl_setopt($curl, CURLOPT_URL, $url);
// Make the request
$response = curl_exec($curl);
$response_info = curl_getinfo($curl);
// Handle the response
if ($response_info['http_code'] == 0) {
throw new Exception("TIMEOUT: api call to " . $url .
" took more than 5s to return" );
} else if ($response_info['http_code'] == 200) {
$data = json_decode($response);
} else if ($response_info['http_code'] == 401) {
throw new Exception("Unauthorized API request to " . $url .
": ".json_decode($response)->message );
} else if ($response_info['http_code'] == 404) {
$data = null;
} else {
throw new Exception("Can't connect to the api: " . $url .
" response code: " .
$response_info['http_code']);
}
return $data;
}
/**
* Build a JSON POST object
*/
protected function sanitizeForSerialization($data)
{
if (is_scalar($data) || null === $data) {
$sanitized = $data;
} else if ($data instanceof \DateTime) {
$sanitized = $data->format(\DateTime::ISO8601);
} else if (is_array($data)) {
foreach ($data as $property => $value) {
$data[$property] = $this->sanitizeForSerialization($value);
}
$sanitized = $data;
} else if (is_object($data)) {
$values = array();
foreach (array_keys($data::$swaggerTypes) as $property) {
$values[$property] = $this->sanitizeForSerialization($data->$property);
}
$sanitized = $values;
} else {
$sanitized = (string)$data;
}
return $sanitized;
}
/**
* Take value and turn it into a string suitable for inclusion in
* the path, by url-encoding.
* @param string $value a string which will be part of the path
* @return string the serialized object
*/
public static function toPathValue($value) {
return rawurlencode($value);
}
/**
* Take value and turn it into a string suitable for inclusion in
* the query, by imploding comma-separated if it's an object.
* If it's a string, pass through unchanged. It will be url-encoded
* later.
* @param object $object an object to be serialized to a string
* @return string the serialized object
*/
public static function toQueryValue($object) {
if (is_array($object)) {
return implode(',', $object);
} else {
return $object;
}
}
/**
* Just pass through the header value for now. Placeholder in case we
* find out we need to do something with header values.
* @param string $value a string which will be part of the header
* @return string the header string
*/
public static function toHeaderValue($value) {
return $value;
}
/**
* Deserialize a JSON string into an object
*
* @param object $object object or primitive to be deserialized
* @param string $class class name is passed as a string
* @return object an instance of $class
*/
public static function deserialize($data, $class)
{
if (null === $data) {
$deserialized = null;
} else if (strcasecmp(substr($class, 0, 6),'array[') == 0) {
$subClass = substr($class, 6, -1);
$values = array();
foreach ($data as $value) {
$values[] = self::deserialize($value, $subClass);
}
$deserialized = $values;
} elseif ($class == 'DateTime') {
$deserialized = new \DateTime($data);
} elseif (in_array($class, array('string', 'int', 'float', 'bool'))) {
$data = (is_object($data) || is_array($data)) ? json_encode($data) : $data;
settype($data, $class);
$deserialized = $data;
} else {
$instance = new $class();
foreach ($instance::$swaggerTypes as $property => $type) {
if (isset($data->$property)) {
$instance->$property = self::deserialize($data->$property, $type);
}
}
$deserialized = $instance;
}
return $deserialized;
}
}

View File

@ -1,250 +0,0 @@
#!/usr/bin/env python
"""Wordnik.com's Swagger generic API client. This client handles the client-
server communication, and is invariant across implementations. Specifics of
the methods and models for each application are generated from the Swagger
templates."""
import sys
import os
import re
import urllib
import urllib2
import httplib
import json
import datetime
import mimetypes
import random
import string
from models import *
class ApiClient:
"""Generic API client for Swagger client library builds"""
def __init__(self, apiKey=None, apiServer=None):
if apiKey == None:
raise Exception('You must pass an apiKey when instantiating the '
'APIClient')
self.apiKey = apiKey
self.apiServer = apiServer
self.cookie = None
self.boundary = ''.join(random.choice(string.ascii_letters + string.digits) for _ in range(30))
def callAPI(self, resourcePath, method, queryParams, postData,
headerParams=None, files=None):
url = self.apiServer + resourcePath
headers = {}
if headerParams:
for param, value in headerParams.iteritems():
headers[param] = value
headers['api_key'] = self.apiKey
if self.cookie:
headers['Cookie'] = self.cookie
data = None
if queryParams:
# Need to remove None values, these should not be sent
sentQueryParams = {}
for param, value in queryParams.items():
if value != None:
sentQueryParams[param] = value
url = url + '?' + urllib.urlencode(sentQueryParams)
if method in ['GET']:
#Options to add statements later on and for compatibility
pass
elif method in ['POST', 'PUT', 'DELETE']:
if postData:
postData = self.sanitizeForSerialization(postData)
if 'Content-type' not in headers:
headers['Content-type'] = 'application/json'
data = json.dumps(postData)
elif headers['Content-type'] == 'multipart/form-data':
data = self.buildMultipartFormData(postData, files)
headers['Content-type'] = 'multipart/form-data; boundary={0}'.format(self.boundary)
headers['Content-length'] = str(len(data))
else:
data = urllib.urlencode(postData)
else:
raise Exception('Method ' + method + ' is not recognized.')
request = MethodRequest(method=method, url=url, headers=headers,
data=data)
# Make the request
response = urllib2.urlopen(request)
if 'Set-Cookie' in response.headers:
self.cookie = response.headers['Set-Cookie']
string = response.read()
try:
data = json.loads(string)
except ValueError: # PUT requests don't return anything
data = None
return data
def toPathValue(self, obj):
"""Convert a string or object to a path-friendly value
Args:
obj -- object or string value
Returns:
string -- quoted value
"""
if type(obj) == list:
return urllib.quote(','.join(obj))
else:
return urllib.quote(str(obj))
def sanitizeForSerialization(self, obj):
"""Dump an object into JSON for POSTing."""
if type(obj) == type(None):
return None
elif type(obj) in [str, int, long, float, bool]:
return obj
elif type(obj) == list:
return [self.sanitizeForSerialization(subObj) for subObj in obj]
elif type(obj) == datetime.datetime:
return obj.isoformat()
else:
if type(obj) == dict:
objDict = obj
else:
objDict = obj.__dict__
return {key: self.sanitizeForSerialization(val)
for (key, val) in objDict.iteritems()
if key != 'swaggerTypes'}
if type(postData) == list:
# Could be a list of objects
if type(postData[0]) in safeToDump:
data = json.dumps(postData)
else:
data = json.dumps([datum.__dict__ for datum in postData])
elif type(postData) not in safeToDump:
data = json.dumps(postData.__dict__)
def buildMultipartFormData(self, postData, files):
def escape_quotes(s):
return s.replace('"', '\\"')
lines = []
for name, value in postData.items():
lines.extend((
'--{0}'.format(self.boundary),
'Content-Disposition: form-data; name="{0}"'.format(escape_quotes(name)),
'',
str(value),
))
for name, filepath in files.items():
f = open(filepath, 'r')
filename = filepath.split('/')[-1]
mimetype = mimetypes.guess_type(filename)[0] or 'application/octet-stream'
lines.extend((
'--{0}'.format(self.boundary),
'Content-Disposition: form-data; name="{0}"; filename="{1}"'.format(escape_quotes(name), escape_quotes(filename)),
'Content-Type: {0}'.format(mimetype),
'',
f.read()
))
lines.extend((
'--{0}--'.format(self.boundary),
''
))
return '\r\n'.join(lines)
def deserialize(self, obj, objClass):
"""Derialize a JSON string into an object.
Args:
obj -- string or object to be deserialized
objClass -- class literal for deserialzied object, or string
of class name
Returns:
object -- deserialized object"""
# Have to accept objClass as string or actual type. Type could be a
# native Python type, or one of the model classes.
if type(objClass) == str:
if 'list[' in objClass:
match = re.match('list\[(.*)\]', objClass)
subClass = match.group(1)
return [self.deserialize(subObj, subClass) for subObj in obj]
if (objClass in ['int', 'float', 'long', 'dict', 'list', 'str', 'bool', 'datetime']):
objClass = eval(objClass)
else: # not a native type, must be model class
objClass = eval(objClass + '.' + objClass)
if objClass in [int, long, float, dict, list, str, bool]:
return objClass(obj)
elif objClass == datetime:
# Server will always return a time stamp in UTC, but with
# trailing +0000 indicating no offset from UTC. So don't process
# last 5 characters.
return datetime.datetime.strptime(obj[:-5],
"%Y-%m-%dT%H:%M:%S.%f")
instance = objClass()
for attr, attrType in instance.swaggerTypes.iteritems():
if obj is not None and attr in obj and type(obj) in [list, dict]:
value = obj[attr]
if attrType in ['str', 'int', 'long', 'float', 'bool']:
attrType = eval(attrType)
try:
value = attrType(value)
except UnicodeEncodeError:
value = unicode(value)
except TypeError:
value = value
setattr(instance, attr, value)
elif (attrType == 'datetime'):
setattr(instance, attr, datetime.datetime.strptime(value[:-5],
"%Y-%m-%dT%H:%M:%S.%f"))
elif 'list[' in attrType:
match = re.match('list\[(.*)\]', attrType)
subClass = match.group(1)
subValues = []
if not value:
setattr(instance, attr, None)
else:
for subValue in value:
subValues.append(self.deserialize(subValue,
subClass))
setattr(instance, attr, subValues)
else:
setattr(instance, attr, self.deserialize(value,
objClass))
return instance
class MethodRequest(urllib2.Request):
def __init__(self, *args, **kwargs):
"""Construct a MethodRequest. Usage is the same as for
`urllib2.Request` except it also takes an optional `method`
keyword argument. If supplied, `method` will be used instead of
the default."""
if 'method' in kwargs:
self.method = kwargs.pop('method')
return urllib2.Request.__init__(self, *args, **kwargs)
def get_method(self):
return getattr(self, 'method', urllib2.Request.get_method(self))

View File

@ -1,76 +0,0 @@
/**
* 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.
* You may obtain a copy of the License at
*
* 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.
*/
package com.wordnik.swagger.codegen
import com.wordnik.swagger.codegen.model._
object BasicAndroidJavaClient extends BasicAndroidJavaGenerator {
def main(args: Array[String]) = generateClient(args)
}
class BasicAndroidJavaGenerator extends BasicJavaGenerator {
override def typeMapping = super.typeMapping ++ Map(
"file" -> "File")
override def importMapping = super.importMapping ++ Map(
"Set" -> "java.util.Set")
override def defaultIncludes = Set(
"Integer",
"String",
"Long",
"Short",
"Char",
"Byte",
"Float",
"Double",
"Boolean",
"AnyRef",
"Any")
// package for api invoker, error files
override def invokerPackage:Option[String] = Some("com.wordnik.client")
override def templateDir = "android-java"
// where to write generated code
override def destinationDir = "generated-code/android-java/src/main/java"
// package for models
override def modelPackage: Option[String] = Some("com.wordnik.client.model")
// package for api classes
override def apiPackage: Option[String] = Some("com.wordnik.client.api")
/**
* you should override these params for generating the pom.xml and processing
* additional params
**/
additionalParams ++= Map(
"artifactId" -> "android-client",
"artifactVersion" -> "1.0.0",
"groupId" -> "com.wordnik")
// supporting classes
override def supportingFiles = List(
("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"),
("pom.mustache", "generated-code/android-java", "pom.xml")
)
}

View File

@ -1,397 +0,0 @@
/**
* 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.
* You may obtain a copy of the License at
*
* 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.
*/
package com.wordnik.swagger.codegen
import com.wordnik.swagger.codegen._
import com.wordnik.swagger.codegen.util._
import com.wordnik.swagger.codegen.language.CodegenConfig
import com.wordnik.swagger.codegen.spec.SwaggerSpecValidator
import com.wordnik.swagger.codegen.model._
import com.wordnik.swagger.codegen.model.SwaggerSerializers
import com.wordnik.swagger.codegen.spec.ValidationMessage
import com.wordnik.swagger.codegen.spec.SwaggerSpec._
import com.wordnik.swagger.util.ValidationException
import java.io.{ File, FileWriter }
import net.iharder.Base64
import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization.write
import scala.io._
import scala.collection.JavaConversions._
import scala.collection.mutable.{ ListBuffer, HashMap, HashSet }
import scala.io.Source
abstract class BasicGenerator extends CodegenConfig with PathUtil {
implicit val formats = SwaggerSerializers.formats("1.2")
def packageName = "com.wordnik.client"
def templateDir = "src/main/resources/scala"
def destinationDir = "generated-code/src/main/scala"
def fileSuffix = ".scala"
override def invokerPackage: Option[String] = Some("com.wordnik.client.common")
override def modelPackage: Option[String] = Some("com.wordnik.client.model")
override def apiPackage: Option[String] = Some("com.wordnik.client.api")
var codegen = new Codegen(this)
var fileMap: Option[String] = None
@deprecated(message = "please use the generate function", since = "2.0.16")
def generateClient(args: Array[String]): Unit = {
generateClientWithoutExit(args)
System.exit(0)
}
@deprecated(message = "please use the generate function", since = "2.0.16")
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/")
}
val host = args(0)
val apiKey = if(args.length > 1) Some(args(1)) else None
val authorization = authenticate(apiKey)
val opts = new ClientOpts()
opts.uri = host
opts.auth = authorization
opts.properties = Map("fileMap" -> sys.props("fileMap"))
generate(opts)
}
def generate(opts: ClientOpts) = {
if (opts == null) {
throw new RuntimeException("Need url to resource listing as argument. You can also specify VM Argument -DfileMap=/path/to/folder/containing.resources.json/")
}
val host = opts.uri
val authorization = opts.auth
fileMap = Option(opts.properties.getOrElse("fileMap", null))
val doc = ResourceExtractor.fetchListing(getResourcePath(host, fileMap), authorization)
additionalParams ++= opts.properties
val apis: List[ApiListing] = getApis(host, doc, authorization)
val errors = new ListBuffer[ValidationError] ++ SwaggerValidator.validate(doc)
for(api <- apis)
SwaggerValidator.validate(api, errors)
errors.filter(_.severity == SwaggerValidator.ERROR).size match {
case i: Int if i > 0 => {
println("********* Failed to read swagger json!")
errors.foreach(msg => {
println(msg)
})
Option(System.getProperty("skipErrors")) match {
case Some(str) => println("**** ignoring errors and continuing")
case None => {
val out = new StringBuilder
errors.foreach(m => out.append(m).append("\n"))
println(errors)
throw new ValidationException(400, "Failed validation", errors.toList)
}
}
}
case 0 =>
}
implicit val basePath = getBasePath(host, doc.basePath, fileMap)
new SwaggerSpecValidator(doc, apis).validate()
val allModels = new HashMap[String, Model]
val operations = extractApiOperations(apis, allModels)
val operationMap: Map[(String, String), List[(String, Operation)]] =
groupOperationsToFiles(operations)
val modelMap = prepareModelMap(allModels.toMap)
val modelFileContents = writeFiles(modelMap, modelTemplateFiles.toMap)
val modelFiles = new ListBuffer[File]()
for((filename, contents) <- modelFileContents) {
val file = new java.io.File(filename)
modelFiles += file
file.getParentFile().mkdirs
val fw = new FileWriter(filename, false)
fw.write(contents + "\n")
fw.close()
}
val apiBundle = prepareApiBundle(operationMap.toMap)
val apiInfo = writeFiles(apiBundle, apiTemplateFiles.toMap)
val apiFiles = new ListBuffer[File]()
apiInfo.map(m => {
val filename = m._1
val file = new java.io.File(filename)
apiFiles += file
file.getParentFile().mkdirs
val fw = new FileWriter(filename, false)
fw.write(m._2 + "\n")
fw.close()
println("wrote api " + filename)
})
codegen.writeSupportingClasses2(apiBundle, modelMap, doc.apiVersion) ++
modelFiles ++ apiFiles
}
/**
* applies a template to each of the models
*/
def writeFiles(models: List[Map[String, AnyRef]], templates: Map[String, String]): List[(String, String)] = {
val output = new ListBuffer[Tuple2[String, String]]
models.foreach(m => {
for ((templateFile, suffix) <- templates) {
val imports = m.getOrElse("imports", None)
val filename = m("outputDirectory").toString + File.separator + m("filename").toString + suffix
output += Tuple2(filename, generateSource(m, templateFile))
}
})
output.toList
}
def generateSource(bundle: Map[String, AnyRef], templateFile: String): String = {
val rootDir = new java.io.File(".")
val (resourcePath, (engine, template)) = Codegen.templates.getOrElseUpdate(templateFile, codegen.compileTemplate(templateFile, Some(rootDir)))
var output = engine.layout(resourcePath, template, bundle)
engine.compiler.shutdown
output
}
def getApis(host: String, doc: ResourceListing, authorization: Option[ApiKeyValue]): List[ApiListing] = {
implicit val basePath = getBasePath(host, doc.basePath, fileMap)
println("base path is " + basePath)
val apiReferences = doc.apis
if (apiReferences == null)
throw new Exception("No APIs specified by resource")
ApiExtractor.fetchApiListings(doc.swaggerVersion, basePath, apiReferences, authorization)
}
def authenticate(apiKey: Option[String]): Option[ApiKeyValue] = {
val headerAuth = sys.props.get("header") map { e =>
// this is ugly and will be replaced with proper arg parsing like in ScalaAsyncClientGenerator soon
val authInfo = e.split(":")
ApiKeyValue(authInfo(0), "header", authInfo(1))
}
val basicAuth = sys.props.get("auth.basic") map { e =>
val creds = if (e.contains(":")) Base64.encodeBytes(e.getBytes) else e
ApiKeyValue("Authorization", "header", s"Basic $creds")
}
val apiKeyAuth = apiKey map { key =>
ApiKeyValue("api_key", "query", key)
}
headerAuth orElse basicAuth orElse apiKeyAuth
}
def extractApiOperations(apiListings: List[ApiListing], allModels: HashMap[String, Model] )(implicit basePath:String) = {
val output = new ListBuffer[(String, String, Operation)]
apiListings.foreach(apiDescription => {
val basePath = apiDescription.basePath
val resourcePath = apiDescription.resourcePath
if(apiDescription.apis != null) {
apiDescription.apis.foreach(api => {
for ((apiPath, operation) <- ApiExtractor.extractApiOperations(basePath, api)) {
output += Tuple3(basePath, apiPath, operation)
}
})
}
output.map(op => processApiOperation(op._2, op._3))
allModels ++= CoreUtils.extractApiModels(apiDescription)
})
output.toList
}
/**
* creates a map of models and properties needed to write source
*/
def prepareModelMap(models: Map[String, Model]): List[Map[String, AnyRef]] = {
val allImports = new HashSet[String]
val outputDirectory = (destinationDir + File.separator + modelPackage.getOrElse("").replace(".", File.separator))
(for ((name, schema) <- models) yield {
if (!defaultIncludes.contains(name)) {
val modelMap: Map[String, AnyRef] = codegen.modelToMap(name, schema)
val imports = modelMap("imports").asInstanceOf[Set[Map[String, AnyRef]]]
val models: List[Map[String, Map[String, AnyRef]]] = List(Map("model" -> modelMap))
val m = new HashMap[String, AnyRef]
m += "imports" -> processImports(imports)
m += "name" -> toModelName(name)
m += "className" -> name
m += "filename" -> toModelFilename(name)
m += "apis" -> None
m += "models" -> models
m += "package" -> modelPackage
m += "invokerPackage" -> invokerPackage
m += "outputDirectory" -> outputDirectory
m += "newline" -> "\n"
m += "modelPackage" -> modelPackage
m += "modelJson" -> codegen.writeJson(schema)
m ++= additionalParams
Some(m.toMap)
}
else None
}).flatten.toList
}
def processImports(ii: Set[Map[String, AnyRef]]) = {
val allImports = new HashSet[String]()
ii.foreach(_.map(m => allImports += m._2.asInstanceOf[String]))
val imports = new ListBuffer[Map[String, String]]
val includedModels = new HashSet[String]
val importScope = modelPackage match {
case Some(s) => s + "."
case _ => ""
}
// do the mapping before removing primitives!
allImports.foreach(value => {
val model = toModelName(value.asInstanceOf[String])
includedModels.contains(model) match {
case false => {
importMapping.containsKey(model) match {
case true => {
if(!imports.flatten.map(m => m._2).toSet.contains(importMapping(model))) {
imports += Map("import" -> importMapping(model))
}
}
case false =>
}
}
case true =>
}
})
allImports --= defaultIncludes
allImports --= primitives
allImports --= containers
allImports.foreach(i => {
val model = toModelName(i)
includedModels.contains(model) match {
case false => {
importMapping.containsKey(model) match {
case true =>
case false => {
if(!imports.flatten.map(m => m._2).toSet.contains(importScope + model)){
imports += Map("import" -> (importScope + model))
}
}
}
}
case true => // no need to add the model
}
})
imports
}
def prepareApiBundle(apiMap: Map[(String, String), List[(String, Operation)]] ): List[Map[String, AnyRef]] = {
(for ((identifier, operationList) <- apiMap) yield {
val basePath = identifier._1
val name = identifier._2
val className = toApiName(name)
val allImports = new HashSet[String]
val operations = new ListBuffer[AnyRef]
val o = new ListBuffer[AnyRef]
val classNameToOperationList = new HashMap[String, ListBuffer[AnyRef]]
for ((apiPath, operation) <- operationList) {
CoreUtils.extractModelNames(operation).foreach(i => allImports += i)
}
val imports = new ListBuffer[Map[String, String]]
val includedModels = new HashSet[String]
val modelList = new ListBuffer[Map[String, AnyRef]]
val importScope = modelPackage match {
case Some(s) => s + "."
case None => ""
}
allImports --= defaultIncludes
allImports --= primitives
allImports --= containers
allImports.foreach(i => {
val model = toModelName(i)
if(!includedModels.contains(model) && !importMapping.containsKey(model)) {
if(!imports.flatten.map(m => m._2).toSet.contains(importScope + model)){
imports += Map("import" -> (importScope + model))
}
}
})
val names = new HashSet[String]
for((path, operation) <- operationList) {
val op = codegen.apiToMap(path, operation)
val nickname = op.getOrElse("nickname", op("httpMethod")).asInstanceOf[String]
var updatedNickname = nickname
if(names.contains(nickname)) {
var counter = 0
var done = false
while(!done) {
updatedNickname = nickname + "_" + className + "_" + counter
if(!names.contains(updatedNickname)) done = true
counter += 1
}
}
names += updatedNickname
o += (Map("path" -> path) ++ op ++ Map("nickname" -> updatedNickname))
}
operations += Map("operation" -> o)
val m = new HashMap[String, AnyRef]
m += "imports" -> imports
m += "baseName" -> name
m += "filename" -> toApiFilename(name)
m += "name" -> toApiName(name)
m += "classname" -> className
m += "className" -> className
m += "basePath" -> basePath
m += "package" -> apiPackage
m += "invokerPackage" -> invokerPackage
m += "operations" -> operations
m += "models" -> None
m += "outputDirectory" -> (destinationDir + File.separator + apiPackage.getOrElse("").replace(".", File.separator))
m += "newline" -> "\n"
m += "modelPackage" -> modelPackage
m ++= additionalParams
Some(m.toMap)
}).flatten.toList
}
def groupOperationsToFiles(operations: List[(String, String, Operation)]): Map[(String, String), List[(String, Operation)]] = {
val opMap = new HashMap[(String, String), ListBuffer[(String, Operation)]]
for ((basePath, apiPath, operation) <- operations) {
val className = resourceNameFromFullPath(apiPath)
val listToAddTo = opMap.getOrElse((basePath, className), {
val l = new ListBuffer[(String, Operation)]
opMap += (basePath, className) -> l
l
})
listToAddTo += Tuple2(apiPath, operation)
}
opMap.map(m => (m._1, m._2.toList)).toMap
}
}

View File

@ -1,166 +0,0 @@
/**
* 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.
* You may obtain a copy of the License at
*
* 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.
*/
package com.wordnik.swagger.codegen
import com.wordnik.swagger.codegen.model._
import java.io.File
object BasicPythonGenerator extends BasicPythonGenerator {
def main(args: Array[String]) = generateClient(args)
}
class BasicPythonGenerator extends BasicGenerator {
// template used for models
modelTemplateFiles += "model.mustache" -> ".py"
// template used for models
apiTemplateFiles += "api.mustache" -> ".py"
// location of templates
override def templateDir = "python"
// where to write generated code
override def destinationDir = "generated-code/python"
// package for models
override def modelPackage: Option[String] = Some("models")
// package for apis
override def apiPackage = None
// file suffix
override def fileSuffix = ".py"
// reserved words which need special quoting
// These will all be object properties, in which context we don't need
// to worry about escaping them for Python.
override def reservedWords = Set()
// import/require statements for specific datatypes
override def importMapping = Map()
// response classes
override def processResponseClass(responseClass: String): Option[String] = {
typeMapping.contains(responseClass) match {
case true => Some(typeMapping(responseClass))
case false => {
responseClass match {
case "void" => None
case e: String => {
responseClass.startsWith("List") match {
case true => Some("list")
case false => Some(responseClass)
}
}
}
}
}
}
override def processResponseDeclaration(responseClass: String): Option[String] = {
typeMapping.contains(responseClass) match {
case true => Some(typeMapping(responseClass))
case false => {
responseClass match {
case "void" => None
case e: String => {
responseClass.startsWith("List") match {
case true => {
val responseSubClass = responseClass.dropRight(1).substring(5)
typeMapping.contains(responseSubClass) match {
case true => Some("list[" + typeMapping(responseSubClass) + "]")
case false => Some("list[" + responseSubClass + "]")
}
}
case false => Some(responseClass)
}
}
}
}
}
}
override def typeMapping = Map(
"integer" -> "int",
"float" -> "float",
"long" -> "long",
"double" -> "float",
"Array" -> "list",
"boolean" -> "bool",
"string" -> "str",
"Date" -> "datetime"
)
override def toDeclaredType(dt: String): String = {
val declaredType = typeMapping.getOrElse(dt, dt)
declaredType.startsWith("Array") match {
case true => {
val innerType = dt.dropRight(1).substring(6)
typeMapping.contains(innerType) match {
case true => "list[" + typeMapping(innerType) + "]"
case false => "list[" + innerType + "]"
}
}
case _ => {
declaredType
}
}
}
override def toDeclaration(obj: ModelProperty) = {
var declaredType = toDeclaredType(obj.`type`)
declaredType match {
case "Array" => declaredType = "list"
case e: String => {
e
}
}
val defaultValue = toDefaultValue(declaredType, obj)
declaredType match {
case "list" => {
val inner = {
obj.items match {
case Some(items) => items.ref.getOrElse(items.`type`)
case _ => {
println("failed on " + declaredType + ", " + obj)
throw new Exception("no inner type defined")
}
}
}
declaredType += "[" + toDeclaredType(inner) + "]"
"list"
}
case _ =>
}
(declaredType, defaultValue)
}
// escape keywords
override def escapeReservedWord(word: String) = "`" + word + "`"
// supporting classes
override def supportingFiles = List(
("__init__.mustache", destinationDir, "__init__.py"),
("swagger.mustache", destinationDir + File.separator + apiPackage.getOrElse(""),
"swagger.py"),
("__init__.mustache", destinationDir + File.separator +
modelPackage.getOrElse(""), "__init__.py"))
}

View File

@ -1,222 +0,0 @@
/**
* 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.
* You may obtain a copy of the License at
*
* 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.
*/
package com.wordnik.swagger.codegen
import com.wordnik.swagger.codegen.model._
object BasicScalaGenerator extends BasicScalaGenerator {
def main(args: Array[String]) = generateClient(args)
}
class BasicScalaGenerator extends BasicGenerator {
override def defaultIncludes = Set(
"Int",
"String",
"Long",
"Short",
"Char",
"Byte",
"Float",
"Double",
"Boolean",
"AnyRef",
"Any")
override def typeMapping = Map(
"array" -> "List",
"set" -> "Set",
"boolean" -> "Boolean",
"string" -> "String",
"int" -> "Int",
"long" -> "Long",
"float" -> "Float",
"byte" -> "Byte",
"short" -> "Short",
"char" -> "Char",
"long" -> "Long",
"double" -> "Double",
"object" -> "Any",
"file" -> "File")
// template used for models
modelTemplateFiles += "model.mustache" -> ".scala"
// template used for models
apiTemplateFiles += "api.mustache" -> ".scala"
// location of templates
override def templateDir = "scala"
// where to write generated code
override def destinationDir = "generated-code/scala/src/main/scala"
// reserved words which need special quoting
override def reservedWords =
Set(
"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")
// import/require statements for specific datatypes
override def importMapping = Map(
"Date" -> "java.util.Date",
"File" -> "java.io.File"
)
// package for models
override def modelPackage: Option[String] = Some("com.wordnik.client.model")
// package for api classes
override def apiPackage: Option[String] = Some("com.wordnik.client.api")
// response classes--if you don't want a response class, override and set to None
override def processResponseClass(responseClass: String): Option[String] = {
responseClass match {
case "void" => None
case e: String => Some(typeMapping.getOrElse(e, e))
}
}
override def processResponseDeclaration(responseClass: String): Option[String] = {
responseClass match {
case "void" => None
case e: String => {
val ComplexTypeMatcher = "(.*)\\[(.*)\\].*".r
val t = e match {
case ComplexTypeMatcher(container, inner) => {
e.replaceAll(container, typeMapping.getOrElse(container.toLowerCase, container))
}
case _ => e
}
Some(typeMapping.getOrElse(t, t))
}
}
}
override def toDeclaredType(dt: String): String = {
val declaredType = dt.indexOf("[") match {
case -1 => dt
case n: Int => {
if (dt.substring(0, n) == "Array")
"List" + dt.substring(n)
else if (dt.substring(0, n) == "Set")
"Set" + dt.substring(n)
else dt
}
}
typeMapping.getOrElse(declaredType, declaredType)
}
override def toDeclaration(obj: ModelProperty): (String, String) = {
obj.`type` match {
case "Array" => {
val inner = {
obj.items match {
case Some(items) => items.ref.getOrElse(items.`type`)
case _ => {
println("failed on " + obj)
throw new Exception("no inner type defined")
}
}
}
val e = "List[%s]".format(toDeclaredType(inner))
(e, toDefaultValue(inner, obj))
}
case "List" => {
val inner = {
obj.items match {
case Some(items) => items.ref.getOrElse(items.`type`)
case _ => {
println("failed on " + obj)
throw new Exception("no inner type defined")
}
}
}
val e = "List[%s]".format(toDeclaredType(inner))
(e, toDefaultValue(inner, obj))
}
case "Set" => {
val inner = {
obj.items match {
case Some(items) => items.ref.getOrElse(items.`type`)
case _ => {
println("failed on " + obj)
throw new Exception("no inner type defined")
}
}
}
val e = "Set[%s]".format(toDeclaredType(inner))
(e, toDefaultValue(inner, obj))
}
case e: String => (toDeclaredType(e), toDefaultValue(e, obj))
}
}
// escape keywords
override def escapeReservedWord(word: String) = "`" + word + "`"
/**
* you should override these params for generating the pom.xml and processing
* additional params
**/
additionalParams ++= Map(
"artifactId" -> "scala-client",
"artifactVersion" -> "1.0.0",
"groupId" -> "com.wordnik",
"asyncHttpClient" -> "false")
// supporting classes
override def supportingFiles = List(
("apiInvoker.mustache", destinationDir + "/com/wordnik/client", "ApiInvoker.scala"),
("pom.mustache", "generated-code/scala", "pom.xml"))
}

View File

@ -1,553 +0,0 @@
/**
* 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.
* You may obtain a copy of the License at
*
* 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.
*/
package com.wordnik.swagger.codegen
import com.wordnik.swagger.codegen.model._
import com.wordnik.swagger.codegen.util.CoreUtils
import com.wordnik.swagger.codegen.language.CodegenConfig
import com.wordnik.swagger.codegen.spec.SwaggerSpec._
import org.json4s.jackson.JsonMethods._
import org.json4s.jackson.Serialization.write
import org.fusesource.scalate._
import org.fusesource.scalate.layout.DefaultLayoutStrategy
import org.fusesource.scalate.mustache._
import org.fusesource.scalate.support.ScalaCompiler
import java.io.{ File, FileWriter, InputStream }
import org.apache.commons.io.FileUtils
import scala.io.Source
import scala.collection.mutable.{ HashMap, ListBuffer, HashSet }
import scala.collection.JavaConversions._
object Codegen {
val templates = new HashMap[String, (String, (TemplateEngine, Template))]
}
class Codegen(config: CodegenConfig) {
implicit val formats = SwaggerSerializers.formats("1.2")
def compileTemplate(templateFile: String, rootDir: Option[File] = None, engine: Option[TemplateEngine] = None): (String, (TemplateEngine, Template)) = {
val engine = new TemplateEngine(rootDir orElse Some(new File(".")))
val srcName = config.templateDir + "/" + templateFile
val srcStream = {
getClass.getClassLoader.getResourceAsStream(srcName) match {
case is: java.io.InputStream => is
case _ => {
val f = new java.io.File(srcName)
if (!f.exists) throw new Exception("Missing template: " + srcName)
else new java.io.FileInputStream(f)
}
}
}
val template = engine.compile(
TemplateSource.fromText(config.templateDir + File.separator + templateFile,
Source.fromInputStream(srcStream).mkString))
(srcName, engine -> template)
}
def rawAllowableValuesToString(v: AllowableValues) = {
v match {
case av: AllowableListValues => {
av
}
case av: AllowableRangeValues => {
av
}
case _ => None
}
}
def allowableValuesToString(v: AllowableValues) = {
v match {
case av: AllowableListValues => {
Some(av.values.mkString("LIST[", ",", "]"))
}
case av: AllowableRangeValues => {
Some("RANGE[" + av.min + "," + av.max + "]")
}
case _ => None
}
}
def apiToMap(path: String, operation: Operation): Map[String, AnyRef] = {
var bodyParam: Option[String] = None
var queryParams = new ListBuffer[AnyRef]
val pathParams = new ListBuffer[AnyRef]
val headerParams = new ListBuffer[AnyRef]
val bodyParams = new ListBuffer[AnyRef]
val formParams = new ListBuffer[AnyRef]
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 => {
val params = new HashMap[String, AnyRef]
params += "code" -> param.code.toString()
params += "reason" -> param.message
if (!param.responseModel.isEmpty)
params += "responseModel" -> param.responseModel
params += "hasMore" -> "true"
errorList += params
})
}
if (operation.parameters != null) {
operation.parameters.foreach(param => {
val params = new HashMap[String, AnyRef]
params += (param.paramType + "Parameter") -> "true"
params += "type" -> param.paramType
params += "defaultValue" -> config.toDefaultValue(param.dataType, param.defaultValue.getOrElse(""))
params += "swaggerDataType" -> param.dataType
params += "description" -> param.description
params += "hasMore" -> "true"
params += "allowMultiple" -> param.allowMultiple.toString
if(param.dataType.toLowerCase() == "file") params += "isFile" -> "true"
else params += "notFile" -> "true"
val u = param.dataType.indexOf("[") match {
case -1 => config.toDeclaredType(param.dataType)
case n: Int => {
val ComplexTypeMatcher = "(.*)\\[(.*)\\].*".r
val ComplexTypeMatcher(container, basePart) = param.dataType
config.toDeclaredType(container + "[" + config.toDeclaredType(basePart) + "]")
}
}
params += "dataType" -> u
params += "getter" -> config.toGetter(param.name, u)
params += "setter" -> config.toSetter(param.name, u)
param.allowableValues match {
case a: AllowableValues => params += "allowableValues" -> allowableValuesToString(a)
case _ =>
}
if (param.required) {
params += "required" -> "true"
} else {
params += "optional" -> "true"
}
param.paramType match {
case "body" => {
params += "paramName" -> "body"
params += "baseName" -> "body"
if (!param.required) {
bodyParamRequired = None
}
bodyParam = Some("body")
bodyParams += params.clone
}
case "path" => {
params += "paramName" -> config.toVarName(param.name)
params += "baseName" -> param.name
params += "required" -> "true"
params -= "optional"
pathParams += params.clone
}
case "query" => {
params += "paramName" -> config.toVarName(param.name)
params += "baseName" -> param.name
queryParams += params.clone
}
case "header" => {
params += "paramName" -> config.toVarName(param.name)
params += "baseName" -> param.name
headerParams += params.clone
}
case "form" => {
params += "paramName" -> config.toVarName(param.name)
params += "baseName" -> param.name
formParams += params.clone
}
case x @ _ => throw new Exception("Unknown parameter type: " + x)
}
paramList += params
})
}
val requiredParams = new ListBuffer[HashMap[String, AnyRef]]
paramList.filter(p => p.contains("required") && p("required") == "true").foreach(param => {
requiredParams += (param.clone += "hasMore" -> "true")
})
requiredParams.size match {
case 0 =>
case _ => requiredParams.last.asInstanceOf[HashMap[String, String]] -= "hasMore"
}
headerParams.size match {
case 0 =>
case _ => headerParams.last.asInstanceOf[HashMap[String, String]] -= "hasMore"
}
queryParams.size match {
case 0 =>
case _ => {
queryParams.head.asInstanceOf[HashMap[String, String]] += "first" -> "true"
queryParams.last.asInstanceOf[HashMap[String, String]] -= "hasMore"
}
}
pathParams.size match {
case 0 =>
case _ => pathParams.last.asInstanceOf[HashMap[String, String]] -= "hasMore"
}
errorList.size match{
case 0 =>
case _ => errorList.last.asInstanceOf[HashMap[String, String]] -= "hasMore"
}
val sp = {
val lb = new ListBuffer[AnyRef]
paramList.foreach(i => {
i += "secondaryParam" -> "true"
i("defaultValue") match {
case Some(e) =>
case None => lb += i
}
})
paramList.foreach(i => {
i("defaultValue") match {
case Some(e) => lb += i
case None =>
}
})
lb.toList
}
paramList.size match {
case 0 =>
case _ => {
sp.head.asInstanceOf[HashMap[String, String]] -= "secondaryParam"
sp.last.asInstanceOf[HashMap[String, String]] -= "hasMore"
}
}
val writeMethods = Set("POST", "PUT", "PATCH")
val properties =
HashMap[String, AnyRef](
"path" -> path,
"nickname" -> config.toMethodName(operation.nickname),
"summary" -> operation.summary,
"notes" -> operation.notes,
"deprecated" -> operation.`deprecated`,
"bodyParam" -> bodyParam,
"bodyParamRequired" -> bodyParamRequired,
"emptyBodyParam" -> (if (writeMethods contains operation.method.toUpperCase) "{}" else ""),
"allParams" -> sp,
"bodyParams" -> bodyParams.toList,
"pathParams" -> pathParams.toList,
"queryParams" -> queryParams.toList,
"headerParams" -> headerParams.toList,
"formParams" -> formParams.toList,
"requiredParams" -> requiredParams.toList,
"errorList" -> errorList,
"httpMethod" -> operation.method.toUpperCase,
"httpMethodLowerCase" -> operation.method.toLowerCase,
operation.method.toLowerCase -> "true")
if (0 < operation.consumes.length) {
val o = new ListBuffer[Map[String, String]]
for(i <- 0 until operation.consumes.length) {
val m = new HashMap[String, String]
if(i < (operation.consumes.length - 1))
m += "hasMore" -> "true"
m += "mediaType" -> operation.consumes(i)
o += m.toMap
}
properties += "consumes" -> o.toList
} else {
properties += "consumes" -> List(Map("mediaType" -> "application/json"))
}
if (0 < operation.produces.length) {
val o = new ListBuffer[Map[String, String]]
for(i <- 0 until operation.produces.length) {
val m = new HashMap[String, String]
if((i + 1) < operation.produces.length)
m += "hasMore" -> "true"
m += "mediaType" -> operation.produces(i)
o += m.toMap
}
properties += "produces" -> o.toList
} else {
properties += "produces" -> List(Map("mediaType" -> "application/json"))
}
if (requiredParams.size > 0) properties += "requiredParamCount" -> requiredParams.size.toString
operation.responseClass.indexOf("[") match {
case -1 => {
val baseType = operation.responseClass
properties += "returnType" -> config.processResponseDeclaration(baseType)
properties += "returnBaseType" -> config.processResponseClass(baseType)
properties += "returnSimpleType" -> "true"
properties += "returnTypeIsPrimitive" -> {
(config.languageSpecificPrimitives.contains(baseType) || primitives.contains(baseType)) match {
case true => Some("true")
case _ => None
}
}
}
case n: Int => {
val ComplexTypeMatcher = ".*\\[(.*)\\].*".r
val ComplexTypeMatcher(basePart) = operation.responseClass
properties += "returnType" -> config.processResponseDeclaration(operation.responseClass.replaceAll(basePart, config.processResponseClass(basePart).get))
properties += "returnContainer" -> config.processResponseClass(operation.responseClass.substring(0, n))
properties += "returnBaseType" -> config.processResponseClass(basePart)
properties += "returnTypeIsPrimitive" -> {
(config.languageSpecificPrimitives.contains(basePart) || primitives.contains(basePart)) match {
case true => Some("true")
case _ => None
}
}
}
}
config.processApiMap(properties.toMap)
}
def modelToMap(className: String, model: Model): Map[String, AnyRef] = {
val data: HashMap[String, AnyRef] =
HashMap(
"classname" -> config.toModelName(className),
"className" -> config.toModelName(className),
"classVarName" -> config.toVarName(className), // suggested name of object created from this class
"modelPackage" -> config.modelPackage,
"description" -> model.description,
"modelJson" -> writeJson(model),
"newline" -> "\n")
val l = new ListBuffer[AnyRef]
val imports = new HashSet[AnyRef]
model.properties.map(prop => {
val propertyDocSchema = prop._2
val dt = propertyDocSchema.`type`
var baseType = dt
// import the object inside the container
if (propertyDocSchema.items != null && !config.typeMapping.contains(dt)) {
// import the container
imports += Map("import" -> dt)
propertyDocSchema.items match {
case Some(items) => baseType = items.ref.getOrElse(items.`type`)
case _ =>
}
}
baseType = config.typeMapping.contains(baseType) match {
case true => config.typeMapping(baseType)
case false => {
// imports += Map("import" -> config.toDeclaredType(baseType))
baseType
}
}
(config.defaultIncludes ++ config.languageSpecificPrimitives).toSet.contains(baseType) match {
case true =>
case _ => {
imports += Map("import" -> baseType)
}
}
val isList = (if (isListType(propertyDocSchema.`type`)) true else None)
val isMap = (if (isMapType(propertyDocSchema.`type`)) true else None)
val isNotContainer = if (!isListType(propertyDocSchema.`type`) && !isMapType(propertyDocSchema.`type`)) true else None
val isContainer = if (isListType(propertyDocSchema.`type`) || isMapType(propertyDocSchema.`type`)) true else None
val properties =
HashMap(
"name" -> config.toVarName(prop._1),
"nameSingular" -> {
val name = config.toVarName(prop._1)
if (name.endsWith("s") && name.length > 1) name.substring(0, name.length - 1) else name
},
"baseType" -> {
if (primitives.contains(baseType))
baseType
else
config.modelPackage match {
case Some(p) => p + "." + baseType
case _ => baseType
}
},
"baseTypeVarName" -> config.toVarName(baseType),
"baseName" -> prop._1,
"datatype" -> config.toDeclaration(propertyDocSchema)._1,
"defaultValue" -> config.toDeclaration(propertyDocSchema)._2,
"description" -> propertyDocSchema.description,
"notes" -> propertyDocSchema.description,
"allowableValues" -> rawAllowableValuesToString(propertyDocSchema.allowableValues),
(if(propertyDocSchema.required) {
data += "hasRequiredParams" -> "true"
"required"
} else "isNotRequired") -> "true",
"getter" -> config.toGetter(prop._1, config.toDeclaration(propertyDocSchema)._1),
"setter" -> config.toSetter(prop._1, config.toDeclaration(propertyDocSchema)._1),
"isList" -> isList,
"isMap" -> isMap,
"isContainer" -> isContainer,
"isNotContainer" -> isNotContainer,
"hasMore" -> "true")
(config.languageSpecificPrimitives.contains(baseType) || primitives.contains(baseType)) match {
case true => properties += "isPrimitiveType" -> "true"
case _ => properties += "complexType" -> config.toModelName(baseType)
}
l += properties
})
if(l.size > 0) {
val last = l.last.asInstanceOf[HashMap[String, String]]
last.remove("hasMore")
}
data += "vars" -> l
data += "imports" -> imports.toSet
config.processModelMap(data.toMap)
}
/**
* gets an input stream from resource or file
*/
def getInputStream(path: String): InputStream = {
getClass.getClassLoader.getResourceAsStream(path) match {
case is: InputStream => is
case _ => new java.io.FileInputStream(path)
}
}
def writeJson(m: AnyRef): String = {
Option(System.getProperty("modelFormat")) match {
case Some(e) if e =="1.1" => write1_1(m)
case _ => pretty(render(parse(write(m))))
}
}
def write1_1(m: AnyRef): String = {
implicit val formats = SwaggerSerializers.formats("1.1")
write(m)
}
def writeSupportingClasses2(
apiBundle: List[Map[String, AnyRef]],
modelsMap: List[Map[String, AnyRef]],
apiVersion: String): Seq[File] = {
val b = new HashMap[String, HashMap[String, AnyRef]]
modelsMap.foreach(m => {
if(m.contains("models")) {
val f = m("models").asInstanceOf[List[Map[String, AnyRef]]]
f.foreach(g => {
val e = new HashMap[String, AnyRef]
val model = g("model").asInstanceOf[Map[String, AnyRef]]
e ++= model
e += "hasMoreModels" -> "true"
b += model("classVarName").toString -> e
})
}
})
val models = new ListBuffer[HashMap[String, AnyRef]]
val keys = b.keys
var count = 0
b.values.foreach(v => {
models += v
count += 1
if(count != keys.size) {
v += "hasMoreModels" -> "true"
}
else {
v.remove("hasMoreModels")
}
})
val f = Map("model" -> models)
val rootDir: Option[File] = Some(new File("."))
val engine = new TemplateEngine(rootDir orElse Some(new File(".")))
val data = Map(
"invokerPackage" -> config.invokerPackage,
"package" -> config.packageName,
"modelPackage" -> config.modelPackage,
"apiPackage" -> config.apiPackage,
"apiInfo" -> Map("apis" -> apiBundle),
"models" -> f,
"apiVersion" -> apiVersion) ++ config.additionalParams
val outputFiles = config.supportingFiles map { file =>
val supportingFile = file._1
val outputDir = file._2
val destFile = file._3
val outputFile = new File(outputDir + File.separator + destFile)
val outputFolder = outputFile.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(outputFile, false)
fw.write(output + "\n")
fw.close()
println("wrote " + outputFile.getPath())
} 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 parentDir = outputFile.getParentFile()
if (parentDir != null && !parentDir.exists) {
println("making directory: " + parentDir.toString + ": " + parentDir.mkdirs)
}
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
}
protected def isListType(dt: String) = isCollectionType(dt, "List") || isCollectionType(dt, "Array") || isCollectionType(dt, "Set")
protected def isMapType(dt: String) = isCollectionType(dt, "Map")
protected def isCollectionType(dt: String, str: String) = {
if (dt.equals(str))
true
else
dt.indexOf("[") match {
case -1 => false
case n: Int => {
if (dt.substring(0, n) == str) {
true
} else false
}
}
}
}

View File

@ -1,503 +0,0 @@
package com.wordnik.swagger.codegen
import java.io.File
import com.wordnik.swagger.codegen.language.CodegenConfig
import com.wordnik.swagger.codegen.model._
import mojolly.inflector.InflectorImports._
import org.rogach.scallop.ScallopConf
import scala.collection.JavaConverters._
import scala.collection.mutable.HashMap
case class SwaggerApi(
clientName: String,
resourceUrl: String,
packageName: String,
apiTemplates: Map[String, String] = Map("api.mustache" -> ".scala"),
modelTemplates: Map[String, String] = Map("model.mustache" -> ".scala"),
apiKey: Option[String] = None,
baseUrl: Option[String] = None,
excludedApis: Set[String] = Set.empty,
excludedModels: Set[String] = Set.empty,
excludedModelPackages: Set[String] = Set.empty,
defaultImports: Map[String, String] = Map.empty)
case class SwaggerGenConfig(
api: SwaggerApi,
templateDir: File,
codeDir: File,
projectRoot: File,
defaultIncludes: Set[String] = Set.empty,
typeMapping: Map[String, String] = Map.empty,
defaultImports: Map[String, String] = Map.empty,
excludedModelPackages: Set[String] = Set.empty)
object AsycnClientGeneratorConf {
val appBanner: String = """
|
|
| .--.--.
| / / '.
|| : /`. / .---. __ ,-.
|; | |--` /. ./| ,----._,. ,----._,. ,' ,'/ /|
|| : ;_ .-'-. ' | ,--.--. / / ' // / ' / ,---. ' | |' |
| \ \ `. /___/ \: |/ \| : | : | / \| | ,'
| `----. \.-'.. ' ' .--. .-. | | .\ | | .\ ./ / ' : /
| __ \ \ /___/ \: '\__\/: . . ; '; . ; '; . ' / | | '
| / /`--' . \ ' .\ ," .--.; ' . . ' . . ' ; /; : |
|'--'. / \ \ ' \ / / ,. |`---`-'| |`---`-'| ' | / | , ;
| `--'---' \ \ |--; : .' .'__/\_: |.'__/\_: | : |---'
| \ \ | | , .-.| : :| : :\ \ /
| '---" `--`---' \ \ / \ \ / `----'
| `--`-' `--`-'
|
| Swagger Codegen, Reverb Technologies Inc. (c) 2009-2013
| For more info, visit: https://developers.helloreverb.com/swagger/
""".stripMargin
}
class AsycnClientGeneratorConf(arguments: Seq[String]) extends ScallopConf(arguments) {
val name = opt[String](required = true, descr = "The name of the generated client.")
val `package` = opt[String](default = Some("com.wordnik.swagger.client.async"), descr = "The package for the generated code.")
val resourceUrl = trailArg[String](descr = "The url to use for fetching the swagger spec from. This can be a http(s) url or a file path.")
val baseUrl = opt[String](descr = "The url to use when you want to override the base url provided by the resource url json.")
val apiKey = opt[String](required = false, descr = "An optional api key to use when calling the swagger api")
val templateDir = opt[String](descr = "The directory that contains the templates for use in this generator", default = Some("asyncscala"))
val codeDir = opt[String](descr = "The directory to use as base for generating code files, this will contain the generated scala files.", default = Some("src/main/scala"), hidden = true)
val projectRoot = opt[String](descr = "The directory to use as project dir, this will receive the build files (*.sbt, *.pom)", default = Some("."))
mainOptions = Seq(resourceUrl, name)
banner("""
|Usage: scala-async.sh [OPTION] spec-url
|
|The scala-async tool generates a swagger api client, using async-http-client
|and stdlib futures.
|
|Options:
|
""".stripMargin)
footer("\nFor more information, visit https://developers.helloreverb.com/swagger/")
}
object ScalaAsyncClientGenerator extends App {
val appBanner: String = AsycnClientGeneratorConf.appBanner
val opts = new AsycnClientGeneratorConf(if (args.nonEmpty) args else Array("--help"))
val rootDir = new File(opts.projectRoot())
val codeDir = {
val cd = opts.codeDir()
if (cd.startsWith("/")) new File(cd)
else new File(rootDir, cd)
}
val resUrl = {
val r = opts.resourceUrl()
if (!r.startsWith("http") && !r.startsWith("file")) sys.props("fileMap") = r
r
}
val baseUrl = opts.baseUrl.get
val cfg = SwaggerGenConfig(
api = SwaggerApi(opts.name(), resUrl, opts.`package`(), apiKey = opts.apiKey.get, baseUrl = baseUrl),
templateDir = new File(opts.templateDir()),
codeDir = new File(rootDir, opts.codeDir()),
projectRoot = rootDir
)
val generator = new ScalaAsyncClientGenerator(cfg)
val clientOpts = new ClientOpts()
val props = new HashMap[String, String]
if(resUrl.startsWith("http"))
clientOpts.uri = resUrl
else
props += "fileMap" -> resUrl
props += "clientName" -> cfg.api.clientName.underscore.pascalize
props += "projectName" -> cfg.api.clientName.underscore.dasherize
clientOpts.properties = props.toMap.asJava
println(appBanner)
generator.generate(clientOpts)
}
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): Seq[File] = {
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.map(_.toMap).toList
}
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" -> apiListF(apis),
"models" -> modelListF(models))
writeSupportingClasses(apis, models, apiVersion, rootDir, dataF)
}
override def compileTemplate(templateFile: String, rootDir: Option[File] = None, engine: Option[TemplateEngine] = None): (String, (TemplateEngine, Template)) = {
val eng = engine getOrElse new TemplateEngine(rootDir orElse Some(new File(".")))
val rn = config.templateDir + File.separator + templateFile
val rrn = "asyncscala" + File.separator + templateFile
val resourceName = if (new File(rn).exists) rn else rrn
val is = getInputStream(resourceName)
if (is == null)
throw new Exception("Missing template: " + resourceName)
val template = eng.compile(TemplateSource.fromText(resourceName,Source.fromInputStream(is).mkString))
(resourceName, eng -> template)
}
*/
}
class ScalaAsyncClientGenerator(cfg: SwaggerGenConfig) extends BasicGenerator {
private[this] val pascalizedClientName = cfg.api.clientName.underscore.pascalize
override val packageName: String = cfg.api.packageName
override val templateDir: String = cfg.templateDir.getPath
override val destinationDir: String = cfg.codeDir.getPath
override val fileSuffix: String = ".scala"
override val modelPackage: Option[String] = Some(packageName + ".model")
override val apiPackage: Option[String] = Some(packageName + ".apis")
override val reservedWords: Set[String] =
Set(
"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")
override val importMapping = Map(
"Date" -> "java.util.Date",
"File" -> "java.io.File"
) ++ cfg.defaultImports ++ cfg.api.defaultImports
override val typeMapping = Map(
"array" -> "List",
"boolean" -> "Boolean",
"string" -> "String",
"int" -> "Int",
"long" -> "Long",
"float" -> "Float",
"byte" -> "Byte",
"short" -> "Short",
"char" -> "Char",
"long" -> "Long",
"double" -> "Double",
"object" -> "Any",
"file" -> "File") ++ cfg.typeMapping
override val defaultIncludes = Set(
"Int",
"String",
"Long",
"Short",
"Char",
"Byte",
"Float",
"Double",
"Boolean",
"AnyRef",
"Any") ++ cfg.defaultIncludes ++ cfg.api.excludedModels
override def supportingFiles = List(
("client.mustache", destinationDir + "/" + cfg.api.packageName.replace('.', '/'), (pascalizedClientName +".scala")),
("sbt.mustache", cfg.projectRoot.getPath, "swagger-client.sbt")
)
modelTemplateFiles ++= cfg.api.modelTemplates
apiTemplateFiles ++= cfg.api.apiTemplates
codegen = new AsyncClientCodegen(cfg.api.clientName, this, Some(cfg.projectRoot))
override def getBasePath(host: String, basePath: String, fileMap: Option[String]): String =
cfg.api.baseUrl.getOrElse(super.getBasePath(host, basePath, fileMap))
/*
override def generateClient(args: Array[String]) = {
val host = cfg.api.resourceUrl
val authorization = {
val apiKey = cfg.api.apiKey
if(apiKey != None)
Some(ApiKeyValue("api_key", "query", apiKey.get))
else
None
}
val doc = {
try {
ResourceExtractor.fetchListing(getResourcePath(host, fileMap), authorization)
} catch {
case e: Exception => throw new Exception("unable to read from " + host, e)
}
}
implicit val basePath = getBasePath(host, doc.basePath, fileMap)
val apiReferences = doc.apis
if (apiReferences == null)
throw new Exception("No APIs specified by resource")
val apis = ApiExtractor.fetchApiListings(doc.swaggerVersion, basePath, apiReferences, authorization)
new SwaggerSpecValidator(doc, apis).validate()
val allModels = new mutable.HashMap[String, Model]
val operations = extractApiOperations(apis, allModels)
val operationMap = groupOperationsToFiles(operations)
val modelMap = prepareModelMap(allModels.toMap)
val modelFileContents = writeFiles(modelMap, modelTemplateFiles.toMap)
val modelFiles = new ListBuffer[File]()
for((filename, contents) <- modelFileContents) {
val file = new java.io.File(filename)
modelFiles += file
file.getParentFile().mkdirs
val fw = new FileWriter(filename, false)
fw.write(contents + "\n")
fw.close()
}
val apiBundle = prepareApiBundle(operationMap.toMap)
val apiInfo = writeFiles(apiBundle, apiTemplateFiles.toMap)
val apiFiles = new ListBuffer[File]()
apiInfo.map(m => {
val filename = m._1
val file = new java.io.File(filename)
apiFiles += file
file.getParentFile().mkdirs
val fw = new FileWriter(filename, false)
fw.write(m._2 + "\n")
fw.close()
println("wrote api " + filename)
})
codegen.writeSupportingClasses2(apiBundle, allModels.toMap, doc.apiVersion) ++
modelFiles ++ apiFiles
}
override def extractApiOperations(apiListings: List[ApiListing], allModels: mutable.HashMap[String, Model] )(implicit basePath:String) = {
val output = new mutable.ListBuffer[(String, String, Operation)]
apiListings.foreach(apiDescription => {
val basePath = apiDescription.basePath
val resourcePath = apiDescription.resourcePath
if(apiDescription.apis != null) {
apiDescription.apis.foreach(api => {
for ((apiPath, operation) <- ApiExtractor.extractApiOperations(basePath, api)) {
output += ((basePath, apiPath, operation))
}
})
}
output.map(op => processApiOperation(op._2, op._3))
allModels ++= CoreUtils.extractApiModels(apiDescription, defaultIncludes, typeMapping)
})
output.toList
}
override def toModelName(name: String) = toDeclaredType(name.pascalize)
*/
override def toApiName(name: String) = {
name.replaceAll("\\{","").replaceAll("\\}", "") match {
case s: String if(s.length > 0) => s.underscore.pascalize + "Client"
case _ => "Client"
}
}
//
// override def nameFromPath(apiPath: String) = resourceNameFromFullPath(apiPath)
//
//
// override def resourceNameFromFullPath(apiPath: String) =
// apiPath.split('/').head.split('.').head
/**
* creates a map of models and properties needed to write source
*/
/*
override def prepareModelMap(models: Map[String, Model]): List[Map[String, AnyRef]] = {
for {
(name, schema) <- (models -- defaultIncludes).toList
if !(cfg.excludedModelPackages ++ cfg.api.excludedModelPackages).exists(schema.qualifiedType.startsWith)
} yield {
Map(
"name" -> toModelName(name),
"className" -> name,
"filename" -> toModelFilename(name),
"apis" -> None,
"models" -> List((name, schema)),
"package" -> modelPackage,
"invokerPackage" -> invokerPackage,
"outputDirectory" -> (destinationDir + File.separator + modelPackage.getOrElse("").replaceAll("\\.", File.separator)),
"newline" -> "\n")
}
}
override def prepareApiBundle(apiMap: Map[(String, String), List[(String, Operation)]] ): List[Map[String, AnyRef]] = {
for {
((basePath, name), operationList) <- apiMap.toList
className = toApiName(name)
} yield {
Map(
"baseName" -> name,
"filename" -> toApiFilename(name),
"name" -> toApiName(name),
"className" -> className,
"basePath" -> basePath,
"package" -> apiPackage,
"invokerPackage" -> invokerPackage,
"apis" -> Map(className -> operationList.toList),
"models" -> None,
"outputDirectory" -> (destinationDir + File.separator + apiPackage.getOrElse("").replaceAll("\\.", File.separator)),
"newline" -> "\n")
}
}
def bundleToSource(bundle:List[Map[String, AnyRef]], templates: Map[String, String]): List[(String, String)] = {
bundle.foldLeft(List.empty[(String, String)]) { (acc, m) =>
templates.foldLeft(acc) { (out, tem) =>
val (file, suffix) = tem
(m("outputDirectory").toString + File.separator + m("filename").toString + suffix) -> codegen.generateSource(m, file) :: acc
}
}
}
def generateAndWrite(bundle: Map[String, AnyRef], templateFile: String) = {
val output = codegen.generateSource(bundle, templateFile)
val outputDir = new File(bundle("outputDirectory").asInstanceOf[String])
outputDir.mkdirs
val filename = outputDir + File.separator + bundle("filename")
val fw = new FileWriter(filename, false)
fw.write(output + "\n")
fw.close()
println("wrote " + filename)
}
*/
// response classes--if you don't want a response class, override and set to None
override def processResponseClass(responseClass: String): Option[String] = {
responseClass match {
case "void" => None //Some("Unit")
case e: String => Some(toDeclaredType(e))
}
}
override def processResponseDeclaration(responseClass: String): Option[String] = {
responseClass match {
case "void" => None //Some("Unit")
case e: String => Some(toDeclaredType(e))
}
}
override def toDeclaredType(dt: String): String = {
val declaredType = (dt.indexOf("[")) match {
case -1 => dt
case n: Int => {
if (dt.substring(0, n).toLowerCase == "array") {
val dtt = dt.substring(n + 1, dt.length - 1)
"List[%s]".format(typeMapping.getOrElse(dtt, dtt))
} else dt
}
}
typeMapping.getOrElse(declaredType, declaredType)
}
override def toDeclaration(obj: ModelProperty): (String, String) = {
obj.`type` match {
case "Array" | "array" => makeContainerType(obj, "List")
case "Set" | "set" => makeContainerType(obj, "Set")
case e: String => (toDeclaredType(e), toDefaultValue(e, obj))
}
}
private def makeContainerType(obj: ModelProperty, container: String): (String, String) = {
val inner = {
obj.items match {
case Some(items) => items.ref.getOrElse(items.`type`)
case _ => throw new Exception("no inner type defined")
}
}
val e = "%s[%s]" format (container, toDeclaredType(inner))
(e, toDefaultValue(inner, obj))
}
// escape keywords
override def escapeReservedWord(word: String) = "`" + word + "`"
}

View File

@ -1,47 +0,0 @@
/**
* 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.
* You may obtain a copy of the License at
*
* 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.
*/
package com.wordnik.swagger.codegen.model
trait AuthorizationType {
def `type`: String
}
case class OAuth(
scopes: List[String],
grantTypes: List[GrantType]) extends AuthorizationType {
override def `type` = "oauth2"
}
case class ApiKey(keyname: String, passAs: String = "header") extends AuthorizationType {
override def `type` = "apiKey"
}
trait GrantType {
def `type`: String
}
case class ImplicitGrant(
loginEndpoint: LoginEndpoint,
tokenName: String) extends GrantType {
def `type` = "implicit"
}
case class AuthorizationCodeGrant(
tokenRequestEndpoint: TokenRequestEndpoint,
tokenEndpoint: TokenEndpoint) extends GrantType {
def `type` = "authorization_code"
}
trait AuthorizationValue
case class ApiKeyValue(keyName: String, passAs: String, value: String) extends AuthorizationValue

View File

@ -1,446 +0,0 @@
/**
* 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.
* You may obtain a copy of the License at
*
* 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.
*/
package com.wordnik.swagger.codegen.spec
import com.wordnik.swagger.codegen.model._
import com.wordnik.swagger.codegen.PathUtil
import com.wordnik.swagger.codegen.spec.SwaggerSpec._
import com.wordnik.swagger.codegen.util.CoreUtils
import java.util.logging.Logger
import String.format
import scala.collection.mutable.ListBuffer
import scala.collection.JavaConversions._
import org.fusesource.scalate.{ TemplateSource, TemplateEngine }
import java.io.{ FileWriter, File }
import scala.io.Source
import scala.collection.mutable.HashSet
import scala.collection.immutable.HashMap
class SwaggerSpecValidator(private val doc: ResourceListing,
private val apis: List[ApiListing],
private val fix: Boolean = true) extends PathUtil {
import ValidationMessage._
private val validationMessages = ListBuffer.empty[ValidationMessage]
private val LOGGER = Logger.getLogger(classOf[SwaggerSpecValidator].getName)
def validate() {
checkRootProperties()
apis.foreach(api => {
fixSubDoc(api)
api.models match {
case Some(models) => {
fixReturnModels(models.toMap, apis)
fixInputDataTypes(models.toMap, apis)
fixModels(models.toMap)
}
case None => LOGGER.warning("No models found for listing: " + api.resourcePath)
}
})
validateResponseModels(apis)
println("----------")
println(this)
}
def validateResponseModels(subDocs: List[ApiListing]) = {
val validModelNames = CoreUtils.extractAllModels(subDocs).map(m => m._1).toSet
val requiredModels = new HashSet[String]
subDocs.foreach(subDoc => {
if (subDoc.apis != null) {
subDoc.apis.foreach(api => {
api.operations.foreach(op => {
requiredModels += {
val responseClass = op.responseClass
responseClass.indexOf("[") match {
case i: Int if (i > 0) => {
CoreUtils.extractBasePartFromType(responseClass)
}
case _ => responseClass
}
}
})
})
}
})
val missingModels = requiredModels.toSet -- (validModelNames ++ primitives)
if (missingModels.size > 0) println("missing models: " + missingModels)
}
def generateReport(host: String, outputFilename: Option[String]) {
outputFilename match {
case Some(o) => {
val rootDir = new java.io.File(".")
val engine = new TemplateEngine(Some(rootDir))
val templateLocation = "validator" + File.separator + "index.mustache"
val template = engine.compile(
TemplateSource.fromText(templateLocation, Source.fromInputStream(getClass.getClassLoader.getResourceAsStream(templateLocation)).mkString))
val output = engine.layout(templateLocation, template, HashMap(
"messages" -> validationMessages,
"host" -> host,
"basePath" -> doc.basePath,
"swaggerVersion" -> doc.swaggerVersion,
"apiVersion" -> doc.apiVersion))
val fw = new FileWriter(o, false)
fw.write(output + "\n")
fw.close()
println("wrote " + o)
}
case None =>
println("Output file location not passed as program argument")
}
}
/**
* Checks the swagger.version, basePath and api.version which is
* expected to be present in root resource listing
*
*/
private def checkRootProperties() {
doc.swaggerVersion match {
case e: String => println("swagger version: " + e)
case _ => !!(doc, RESOURCE_LISTING, "Properties", "Missing swagger version")
}
doc.basePath match {
case e: String => println("basePath: " + e)
case _ => !!(doc, RESOURCE_LISTING, "Properties", "Missing base path")
}
doc.apiVersion match {
case e: String => println("api version: " + e)
case _ => !!(doc, RESOURCE_LISTING, "Properties", "Missing api version", WARNING)
}
}
/**
* this is here because sub documents don't have the same resourcePath as declared in
* the main resource listing
*/
private def fixSubDoc(api: ApiListing) = {
if (api.resourcePath.indexOf(".{format}") == -1) {
doc.apis.foreach(op => {
if (op.path.indexOf(".{format}") > 0 && op.path.replaceAll(".\\{format\\}", "") == api.resourcePath) {
if (fix) {
api.resourcePath = api.resourcePath + ".{format}"
}
}
})
}
}
/**
* this is here because models don't have the proper references to types
*/
private def fixModels(models: Map[String, Model]) = {
val validModelNames = models.map(_._1).toSet
LOGGER.finest("all valid models: " + validModelNames)
for ((name, model) <- models) {
// id of model
getUpdatedType(validModelNames, model.id) match {
case Some(updatedType) => {
if (!model.id.equals(updatedType)) {
!!(model, MODEL, model.id, format("Invalid id. Best guess: %s", updatedType))
LOGGER.finest("updated " + model.id + " to " + updatedType)
if (fix) model.id = updatedType
}
}
case None => {
LOGGER.finest("can't find type for " + model.name + ", type " + model.id)
!!(model, MODEL, model.name, format("Missing type (%s)", model.id))
}
}
model.properties.foreach(prop => {
val subObjectName = prop._1
val subObject = prop._2
if (containers.contains(subObject.`type`)) {
// process the sub object
subObject.items match {
case Some(item) => {
getUpdatedType(validModelNames, item.ref.getOrElse(null)) match {
case Some(updatedType) => {
if (!item.ref.get.equals(updatedType)) {
!!(model, MODEL_PROPERTY, format("%s->%s: %s", model.id, subObjectName, subObject.`type`), format("Invalid ref (%s). Best guess: %s", item.ref, updatedType))
LOGGER.finest("updated subObject.items.ref " + item.ref + " to " + updatedType)
if (fix) {
subObject.items = Some(ModelRef(null, Some(updatedType)))
}
}
}
case None =>
}
}
case _ =>
}
} else if (containers.contains(subObject.`type`)) {
// process the sub object
if (subObject.items != null && subObject.items != None && subObject.items.get.ref != null){
subObject.items match {
case Some(item) => {
getUpdatedType(validModelNames, item.ref.getOrElse(null)) match {
case Some(updatedType) => {
if (!item.ref.equals(updatedType)) {
!!(model, MODEL_PROPERTY, format("%s->%s: %s", model.id, subObjectName, subObject.`type`), format("Invalid ref (%s). Best guess: %s", item.ref, updatedType))
LOGGER.finest("updated subObject.items.ref " + item.ref + " to " + updatedType)
if (fix) subObject.items = Some(ModelRef(null, Some(updatedType)))
}
}
case None => {
!!(model, MODEL_PROPERTY, format("%s->%s: %s", model.id, subObjectName, subObject.`type`), format("Invalid ref (%s).", item.ref))
LOGGER.finest("didn't know what to do with " + item.ref)
}
}
}
case _ =>
}
}
else if (subObject.items != null && subObject.items != None && subObject.items.get.`type` != null) {
subObject.items match {
case Some(item) => {
getUpdatedType(validModelNames, item.`type`) match {
case Some(updatedType) => {
if (!item.`type`.equals(updatedType)) {
!!(model, MODEL_PROPERTY, format("%s->%s: %s", model.id, subObjectName, subObject.`type`), format("Invalid type (%s). Best guess: %s", item.`type`, updatedType))
LOGGER.finest("updated subObject.items.type" + item.`type` + " to " + updatedType)
if (fix) subObject.items = Some(ModelRef(`type` = updatedType))
}
}
case None => {
println("nothing found for " + subObject)
!!(model, MODEL_PROPERTY, format("%s->%s: %s", model.id, subObjectName, subObject.`type`), format("Invalid ref (%s).", item.ref))
LOGGER.finest("didn't know what to do with " + item.ref)
}
}
}
case _ =>
}
}
} else {
getUpdatedType(validModelNames, subObject.`type`) match {
case Some(updatedType) => {
if (!subObject.`type`.equals(updatedType)) {
!!(model, MODEL_PROPERTY, format("%s->%s: %s", model.id, subObjectName, subObject.`type`), format("Invalid type (%s). Best guess: %s", subObject.`type`, updatedType))
LOGGER.finest("updated subObject.getType " + subObject.`type` + " to " + updatedType)
if (fix) subObject.`type` = updatedType
}
}
case None =>
}
}
})
// remove params with invalid names (Pos???)
model.properties = model.properties.filter(prop => {
if (prop._1.indexOf("$") == -1) true
else {
!!(model, MODEL, model.id, format("Invalid property %s. Removing it", prop._1))
LOGGER.finest("removing invalid property " + prop._1)
if (fix) false else true
}
})
}
}
/**
* this is here because input params in operations don't match primitives or model names
*/
private def fixInputDataTypes(models: Map[String, Model], a: List[ApiListing]) = {
val validModelNames = models.map(m => m._1).toSet
// List[ApiListing]
a.foreach(listing => {
if (listing.apis != null) {
listing.apis.foreach(api => {
// List[ApiDescription]
api.operations.foreach(op => {
// List[Operation]
val modelNames = new ListBuffer[String]
if(op.parameters != null) {
op.parameters.foreach(p => {
val dataType = p.dataType
p.paramType match {
case "body" => {
getUpdatedType(validModelNames, dataType) match {
case Some(updatedName) => {
if (!p.dataType.equals(updatedName)) {
// LOGGER.finest("--> updated " + dataType + " to " + updatedName)
!!(p, OPERATION_PARAM, format("%s.%s(body: %s)", apiNameFromPath(api.path), op.nickname, p.dataType), format("Invalid data type %s. Best guess: %s", p.dataType, updatedName))
if (fix) p.dataType = updatedName
}
}
case _ => LOGGER.finest("rats!") // leave it alone
}
}
case "path" => {
getUpdatedType(validModelNames, dataType) match {
case Some(updatedName) => {
// LOGGER.finest("--> updated " + dataType + " to " + updatedName)
!!(p, OPERATION_PARAM, format("%s.%s(path_%s: %s)", apiNameFromPath(api.path), op.nickname, p.name, p.dataType), format("Invalid data type %s. Best guess: %s", p.dataType, updatedName))
if (fix) p.dataType = updatedName
}
case _ => // leave it alone
}
}
case "query" => {
getUpdatedType(validModelNames, dataType) match {
case Some(updatedName) => {
// LOGGER.finest("--> updated " + dataType + " to " + updatedName)
!!(p, OPERATION_PARAM, format("%s.%s(query_%s: %s)", apiNameFromPath(api.path), op.nickname, p.name, p.dataType), format("Invalid %s. Best guess: %s", p.dataType, updatedName))
if (fix) p.dataType = updatedName
}
case _ => // leave it alone
}
}
case _ =>
}
})
}
})
})
}
})
}
/**
* this is here because the return types are inconsistent from the swagger-core-1.02-SNAPSHOT
*/
private def fixReturnModels(models: Map[String, Model], a: List[ApiListing]) = {
val validModelNames = models.map(m => m._1).toSet
// List[ApiListing]
a.foreach(listing => {
if (listing.apis != null) {
listing.apis.foreach(api => {
// List[ApiDescription]
api.operations.foreach(op => {
// List[Operation]
val responseClass = op.responseClass
if (responseClass != null) {
getUpdatedType(validModelNames, responseClass) match {
case Some(updatedName) => {
if (!responseClass.equals(updatedName)) {
LOGGER.finest("--> updated " + responseClass + " to " + updatedName)
!!(op, OPERATION, format("%s.%s(): %s", apiNameFromPath(api.path), op.nickname, op.responseClass), format("Invalid response class. Best guess: %s", updatedName))
if (fix) op.responseClass = updatedName
}
}
case _ => {
} // leave it alone
}
}
})
})
}
})
}
private def getUpdatedType(validModelNames: Set[String], name: String): Option[String] = {
if(name == null) return None
if (validModelNames.contains(name)) {
Some(name)
} else if (name.indexOf("[") > 0) {
// it's a complex value
val ComplexTypeMatcher = ".*\\[(.*)\\].*".r
val ComplexTypeMatcher(basePart) = name
getUpdatedType(validModelNames, basePart) match {
case Some(updatedPart) => {
Some(name.replaceAll(java.util.regex.Pattern.quote(basePart), updatedPart))
}
case _ => None
}
} else if (name.indexOf(".") > 0) {
val basePart = name.split("\\.").last
getUpdatedType(validModelNames, basePart) match {
case Some(updatedPart) => {
Some(updatedPart)
}
case _ => {
None
}
}
} else if (!primitives.contains(name)) {
val pc = name
if (validModelNames.contains(pc)) {
Some(pc)
} else if (pc == "Ok") {
Some("void")
} else if (pc == "Long") {
Some("long")
} else if (pc == "Double") {
Some("double")
} else if (pc == "Float") {
Some("float")
} else if (pc == "Boolean") {
Some("boolean")
} else if (pc == "Integer") {
Some("int")
} else if (pc == "Byte") {
Some("byte")
} else {
None
}
} else {
None
}
}
def !!(element: AnyRef, elementType: String, elementId: String, message: String, level: String = ERROR) {
validationMessages += new ValidationMessage(element, elementType, elementId, message, level)
}
override def toString = {
val out = new StringBuilder
for (v <- validationMessages) {
out.append(v)
out.append('\n')
}
out.toString()
}
}
class ValidationMessage(val element: AnyRef, val elementType: String, val elementId: String, val message: String, val level: String) {
override def toString = level + ": " + elementType + " - " + elementId + " | " + message
}
object ValidationMessage {
val WARNING = "Warning"
val ERROR = "Error"
val RESOURCE_LISTING = "Root Resources Listing"
val RESOURCE = "Resource"
val OPERATION = "Operation"
val OPERATION_PARAM = "Operation Parameter"
val MODEL = "Model"
val MODEL_PROPERTY = "Model Property"
val validationMessages = ListBuffer.empty[ValidationMessage]
}

View File

@ -1,46 +0,0 @@
package com.wordnik.swagger.codegen.util
import com.wordnik.swagger.codegen.model._
import java.net._
import java.io.InputStream
import scala.io.Source
trait RemoteUrl {
def urlToString(url: String, authorization: Option [AuthorizationValue]): String = {
var is: InputStream = null
try{
val conn: URLConnection = authorization match {
case Some(auth: ApiKeyValue) => {
if(auth.passAs == "header") {
val connection = new URL(url).openConnection()
connection.setRequestProperty(auth.keyName, auth.value)
connection
}
else if(auth.passAs == "query") {
new URL(url + "?%s=%s".format(URLEncoder.encode(auth.keyName, "UTF-8"), URLEncoder.encode(auth.value, "UTF-8"))).openConnection()
}
else {
new URL(url).openConnection()
}
}
case None => new URL(url).openConnection()
}
is = conn.getInputStream()
Source.fromInputStream(is).mkString
}
catch {
case e: javax.net.ssl.SSLProtocolException => {
println("there is a problem with the target SSL certificate")
println("**** you may want to run with -Djsse.enableSNIExtension=false\n\n")
e.printStackTrace
throw e
}
case e: Exception => e.printStackTrace; throw e;
}
finally {
if(is != null) is.close()
}
}
}

View File

@ -1,83 +0,0 @@
/**
* 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.
* You may obtain a copy of the License at
*
* 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.
*/
import com.wordnik.swagger.codegen.Codegen
import com.wordnik.swagger.codegen.BasicJavaGenerator
import com.wordnik.swagger.codegen.model._
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import org.scalatest.FlatSpec
import org.scalatest.Matchers
import scala.beans.BeanProperty
import scala.collection.mutable.{ HashMap, LinkedHashMap }
@RunWith(classOf[JUnitRunner])
class CodegenTest extends FlatSpec with Matchers {
val subject = new Codegen(new BasicJavaGenerator)
val testOp = new Operation("GET",
"List All Contacts",
"",
"Array[ContactData]",
"listContacts",
0,
List.empty,
List.empty,
List.empty,
List.empty,
//query param
List(new Parameter("Name", Some("name"), Some("null"), false, false, "String", AnyAllowableValues, "query", None)),
List.empty,
None)
val testModel = new Model("Contact",
"Contact",
"Contact",
//required field
LinkedHashMap("Name" -> new ModelProperty("String", "String", 0, true, None, AnyAllowableValues, None)),
None,
None,
None)
behavior of "Codegen"
/*
* A return specified as "Array" should map to "List"
*/
it should "recognize the returnContainer as a List" in {
val map = subject.apiToMap("/contacts", testOp)
map("returnContainer") should be (Some("List"))
}
/*
* Field first on the query param should be true
*/
it should "have a first field on first query param and should be true" in {
val map = subject.apiToMap("/contacts", testOp)
map("queryParams").asInstanceOf[List[HashMap[String, String]]].head("first") should be ("true")
}
/*
* Field hasRequiredParams should be true
*/
it should "have a hasRequiredParams field and should be true" in {
val map = subject.modelToMap("Contact", testModel)
map("hasRequiredParams") should be ("true")
}
}