mirror of
https://github.com/valitydev/openapi-generator.git
synced 2024-11-06 18:45:23 +00:00
removed cruft
This commit is contained in:
parent
66c6662f42
commit
97fca910a1
137
build.sbt
137
build.sbt
@ -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"
|
@ -1 +0,0 @@
|
||||
sbt.version=0.13.5
|
@ -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
652
samples/html/index.html
Normal 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> — 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> — 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> — 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> — The user name for login </div>
|
||||
<div class="param">password (optional)</div>
|
||||
|
||||
<div class="param-desc"><span class="param-type">Query Parameter</span> — 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> — 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> — name that need to be deleted </div>
|
||||
<div class="param">body (optional)</div>
|
||||
|
||||
<div class="param-desc"><span class="param-type">Body Parameter</span> — 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> — 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> — 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 <= 5 or > 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> — 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 < 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> — 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> — 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> — 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> — 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> — 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 < 10. ID > 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> — 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> — 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> — Updated name of the pet </div>
|
||||
<div class="param">status (optional)</div>
|
||||
|
||||
<div class="param-desc"><span class="param-type">Form Parameter</span> — 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> — </div>
|
||||
<div class="param">petId (required)</div>
|
||||
|
||||
<div class="param-desc"><span class="param-type">Path Parameter</span> — 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> — ID of pet to update </div>
|
||||
<div class="param">additionalMetadata (optional)</div>
|
||||
|
||||
<div class="param-desc"><span class="param-type">Form Parameter</span> — Additional data to pass to server </div>
|
||||
<div class="param">file (optional)</div>
|
||||
|
||||
<div class="param-desc"><span class="param-type">Form Parameter</span> — 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
518
sbt
@ -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[@]}"
|
@ -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)
|
@ -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
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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))
|
||||
|
@ -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")
|
||||
)
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
@ -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"))
|
||||
}
|
@ -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"))
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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 + "`"
|
||||
|
||||
}
|
@ -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
|
||||
|
@ -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]
|
||||
}
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user