mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-06-30 20:50:53 +00:00
Merge branch 'master' of github.com:wordnik/swagger-codegen
This commit is contained in:
commit
3cbf2abc5c
@ -11,7 +11,7 @@
|
||||
* @param string $className the class to attempt to load
|
||||
*/
|
||||
function swagger_autoloader($className) {
|
||||
$currentDir = substr(__FILE__, 0, strrpos(__FILE__, '/'));
|
||||
$currentDir = dirname(__FILE__);
|
||||
if (file_exists($currentDir . '/' . $className . '.php')) {
|
||||
include $currentDir . '/' . $className . '.php';
|
||||
} elseif (file_exists($currentDir . '/models/' . $className . '.php')) {
|
||||
|
@ -11,7 +11,7 @@
|
||||
* @param string $className the class to attempt to load
|
||||
*/
|
||||
function swagger_autoloader($className) {
|
||||
$currentDir = substr(__FILE__, 0, strrpos(__FILE__, '/'));
|
||||
$currentDir = dirname(__FILE__);
|
||||
if (file_exists($currentDir . '/' . $className . '.php')) {
|
||||
include $currentDir . '/' . $className . '.php';
|
||||
} elseif (file_exists($currentDir . '/models/' . $className . '.php')) {
|
||||
|
@ -11,7 +11,7 @@
|
||||
* @param string $className the class to attempt to load
|
||||
*/
|
||||
function swagger_autoloader($className) {
|
||||
$currentDir = substr(__FILE__, 0, strrpos(__FILE__, '/'));
|
||||
$currentDir = dirname(__FILE__);
|
||||
if (file_exists($currentDir . '/' . $className . '.php')) {
|
||||
include $currentDir . '/' . $className . '.php';
|
||||
} elseif (file_exists($currentDir . '/models/' . $className . '.php')) {
|
||||
|
@ -44,15 +44,18 @@ class ApiClient:
|
||||
|
||||
data = None
|
||||
|
||||
if method == 'GET':
|
||||
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 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']:
|
||||
|
||||
@ -95,7 +98,7 @@ class ApiClient:
|
||||
def sanitizeForSerialization(self, obj):
|
||||
"""Dump an object into JSON for POSTing."""
|
||||
|
||||
if not obj:
|
||||
if type(obj) == type(None):
|
||||
return None
|
||||
elif type(obj) in [str, int, long, float, bool]:
|
||||
return obj
|
||||
@ -164,6 +167,8 @@ class ApiClient:
|
||||
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],
|
||||
|
@ -43,15 +43,19 @@ class ApiClient:
|
||||
|
||||
data = None
|
||||
|
||||
if method == 'GET':
|
||||
|
||||
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.parse.urlencode(sentQueryParams)
|
||||
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.parse.urlencode(sentQueryParams)
|
||||
|
||||
if method in ['GET']:
|
||||
|
||||
#Options to add statements later on and for compatibility
|
||||
pass
|
||||
|
||||
elif method in ['POST', 'PUT', 'DELETE']:
|
||||
|
||||
@ -98,7 +102,7 @@ class ApiClient:
|
||||
def sanitizeForSerialization(self, obj):
|
||||
"""Dump an object into JSON for POSTing."""
|
||||
|
||||
if not obj:
|
||||
if type(obj) == type(None):
|
||||
return None
|
||||
elif type(obj) in [str, int, float, bool]:
|
||||
return obj
|
||||
@ -159,6 +163,8 @@ class ApiClient:
|
||||
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],
|
||||
|
1092
src/main/resources/swagger-static/assets/css/bootstrap-responsive.css
vendored
Normal file
1092
src/main/resources/swagger-static/assets/css/bootstrap-responsive.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
6057
src/main/resources/swagger-static/assets/css/bootstrap.css
vendored
Normal file
6057
src/main/resources/swagger-static/assets/css/bootstrap.css
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1
src/main/resources/swagger-static/assets/css/site.css
Normal file
1
src/main/resources/swagger-static/assets/css/site.css
Normal file
@ -0,0 +1 @@
|
||||
site.css
|
135
src/main/resources/swagger-static/assets/css/style.css
Normal file
135
src/main/resources/swagger-static/assets/css/style.css
Normal file
@ -0,0 +1,135 @@
|
||||
.line-numbers {
|
||||
margin-right: 1.0em;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding-bottom: 100px;
|
||||
}
|
||||
|
||||
.column_header_name {
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.column_header_path {
|
||||
width: 350px;
|
||||
}
|
||||
|
||||
.column_header_name .column_header_param_type .column_header_data_type .column_header_return_type {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
.expandable {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.main_content {
|
||||
margin-top: 80px;
|
||||
margin-left: 25px;
|
||||
margin-right: 25px;
|
||||
}
|
||||
|
||||
.header {
|
||||
position: fixed;
|
||||
text-align: left;
|
||||
background-color: black;
|
||||
float: left;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 70px auto;
|
||||
padding-bottom: 20px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 2px 8px 5px;
|
||||
}
|
||||
|
||||
.top-bar h1 a {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.top-bar h1#logo a {
|
||||
width: auto;
|
||||
display: block;
|
||||
clear: none;
|
||||
float: left;
|
||||
background-position: left;;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.top-bar ul li {
|
||||
list-style: none;
|
||||
}
|
||||
|
||||
.top-bar h1#logo span {
|
||||
display: block;
|
||||
clear: none;
|
||||
float: left;
|
||||
padding-top: 10px;
|
||||
padding-left: 10px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.top-bar h1#logo a span.light {
|
||||
color: #ffc97a;
|
||||
color: #666666;
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
.top-bar ul#nav {
|
||||
float: none;
|
||||
clear: both;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
display: block;
|
||||
float: right;
|
||||
clear: none;
|
||||
}
|
||||
|
||||
.top-bar ul#nav li {
|
||||
float: left;
|
||||
clear: none;
|
||||
margin: 0;
|
||||
padding: 2px 10px;
|
||||
border-right: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
.top-bar ul#nav li:first-child, .top-bar ul#nav li.first {
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
.top-bar ul#nav li:last-child, .top-bar ul#nav li.last {
|
||||
padding-right: 0;
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.top-bar ul#nav li {
|
||||
border: none;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.top-bar ul#nav li a {
|
||||
display: block;
|
||||
padding: 8px 10px 8px 10px;
|
||||
color: #999999;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.top-bar ul#nav li a.strong {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.top-bar ul#nav li a:active, .top-bar ul#nav li a.active, .top-bar ul#nav li a:hover {
|
||||
-moz-border-radius: 4px;
|
||||
-webkit-border-radius: 4px;
|
||||
-o-border-radius: 4px;
|
||||
-ms-border-radius: 4px;
|
||||
-khtml-border-radius: 4px;
|
||||
border-radius: 4px;
|
||||
background-image: -webkit-gradient(linear, 0% 100%, 0% 0%, color-stop(0%, #ff5401), color-stop(100%, #ffa014));
|
||||
background-image: -moz-linear-gradient(bottom, #ff5401 0%, #ffa014 100%);
|
||||
background-image: linear-gradient(bottom, #ff5401 0%, #ffa014 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.top-bar ul#nav:hover li {
|
||||
border-color: #222222;
|
||||
}
|
BIN
src/main/resources/swagger-static/assets/images/logo.png
Normal file
BIN
src/main/resources/swagger-static/assets/images/logo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 14 KiB |
2159
src/main/resources/swagger-static/assets/js/bootstrap.js
vendored
Normal file
2159
src/main/resources/swagger-static/assets/js/bootstrap.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2
src/main/resources/swagger-static/assets/js/jquery-1.8.3.min.js
vendored
Normal file
2
src/main/resources/swagger-static/assets/js/jquery-1.8.3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
41
src/main/resources/swagger-static/index.mustache
Normal file
41
src/main/resources/swagger-static/index.mustache
Normal file
@ -0,0 +1,41 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="assets/css/bootstrap.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="assets/css/bootstrap-responsive.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="assets/css/style.css">
|
||||
|
||||
<title>REST API v1.1 Resources | Twitter Developers</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<div class="top-bar">
|
||||
<h1 id="logo"><a class="logo" href="/"><span>Swagger</span><span class="light">API Docs</span></a></h1>
|
||||
</div>
|
||||
</div>
|
||||
<div class="main_content">
|
||||
<h1>API Documentation</h1>
|
||||
{{#apis}}
|
||||
<h2>{{className}}</h2>
|
||||
<table>
|
||||
<tr>
|
||||
<th class="column_header_name">Name</th>
|
||||
<th class="column_header_path">Resource</th>
|
||||
<th class="column_header_notes">Notes</th>
|
||||
</tr>
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
<tr>
|
||||
<td><a href="operations/{{{className}}}.html#{{{nickname}}}">{{{nickname}}}</a></td>
|
||||
<td>{{path}}</td>
|
||||
<td>{{{summary}}}{{#notes}}<div id="{{className}}_{{nickname}}" class="operation expandable">{{notes}}</div>{{/notes}}</td>
|
||||
</tr>
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
</table>
|
||||
{{/apis}}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
82
src/main/resources/swagger-static/operation.mustache
Normal file
82
src/main/resources/swagger-static/operation.mustache
Normal file
@ -0,0 +1,82 @@
|
||||
<!DOCTYPE html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="../assets/css/bootstrap.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="../assets/css/bootstrap-responsive.css" media="screen">
|
||||
<link rel="stylesheet" type="text/css" href="../assets/css/style.css">
|
||||
|
||||
<title>REST API v1.1 Resources | Twitter Developers</title>
|
||||
</head>
|
||||
<body>
|
||||
<div class="header">
|
||||
<div class="top-bar">
|
||||
<h1 id="logo"><a class="logo" href="/"><span>Swagger</span><span class="light">API Docs</span></a></h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="main_content">
|
||||
<h1>{{classname}}</h1>
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
<a name="{{nickname}}"></a>
|
||||
<h2>{{nickname}}</h2>
|
||||
<h3>{{httpMethod}}: {{path}}</h3>
|
||||
<table>
|
||||
<tr>
|
||||
<th class="column_header_name">parameter</th>
|
||||
<th class="column_header_param_type">param type</th>
|
||||
<th class="column_header_data_type">data type</th>
|
||||
<th class="column_header_return_type">response type</th>
|
||||
<th class="column_header_notes">Description</th>
|
||||
</tr>
|
||||
<!-- body params -->
|
||||
{{#bodyParams}}
|
||||
<tr>
|
||||
<td>{{paramName}}<br/>{{#required}}required{{/required}}{{^required}}optional{{/required}}</td>
|
||||
<td>body</td>
|
||||
<td>{{swaggerDataType}}{{#allowMultiple}}*{{/allowMultiple}}</td>
|
||||
<td>{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}-{{/returnType}}</td>
|
||||
<td>{{description}}{{#notes}}<br/><div id="{{className}}_{{nickname}}" class="operation expandable">{{notes}}</div>{{/notes}}</td>
|
||||
</tr>
|
||||
{{/bodyParams}}
|
||||
|
||||
<!-- path params -->
|
||||
{{#pathParams}}
|
||||
<tr>
|
||||
<td>{{paramName}}<br/>{{#required}}required{{/required}}{{^required}}optional{{/required}}</td>
|
||||
<td>path</td>
|
||||
<td>{{swaggerDataType}}{{#allowMultiple}}*{{/allowMultiple}}</td>
|
||||
<td>{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}-{{/returnType}}</td>
|
||||
<td>{{description}}{{#notes}}<br/><div id="{{className}}_{{nickname}}" class="operation expandable">{{notes}}</div>{{/notes}}</td>
|
||||
</tr>
|
||||
{{/pathParams}}
|
||||
|
||||
<!-- query params -->
|
||||
{{#queryParams}}
|
||||
<tr>
|
||||
<td>{{paramName}}<br/>{{#required}}required{{/required}}{{^required}}optional{{/required}}</td>
|
||||
<td>query</td>
|
||||
<td>{{swaggerDataType}}{{#allowMultiple}}*{{/allowMultiple}}</td>
|
||||
<td>{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}-{{/returnType}}</td>
|
||||
<td>{{description}}{{#notes}}<br/><div id="{{className}}_{{nickname}}" class="operation expandable">{{notes}}</div>{{/notes}}</td>
|
||||
</tr>
|
||||
{{/queryParams}}
|
||||
|
||||
<!-- header params -->
|
||||
{{#headerParams}}
|
||||
<tr>
|
||||
<td>{{paramName}}<br/>{{#required}}required{{/required}}{{^required}}optional{{/required}}</td>
|
||||
<td>header</td>
|
||||
<td>{{swaggerDataType}}{{#allowMultiple}}*{{/allowMultiple}}</td>
|
||||
<td>{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}-{{/returnType}}</td>
|
||||
<td>{{description}}{{#notes}}<br/><div id="{{className}}_{{nickname}}" class="operation expandable">{{notes}}</div>{{/notes}}</td>
|
||||
</tr>
|
||||
{{/headerParams}}
|
||||
</table>
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -55,15 +55,15 @@ class BasicJavaGenerator extends BasicGenerator {
|
||||
// location of templates
|
||||
override def templateDir = "Java"
|
||||
|
||||
// where to write generated code
|
||||
override def destinationDir = "generated-code/java/src/main/java"
|
||||
|
||||
// template used for models
|
||||
modelTemplateFiles += "model.mustache" -> ".java"
|
||||
|
||||
// template used for models
|
||||
apiTemplateFiles += "api.mustache" -> ".java"
|
||||
|
||||
// where to write generated code
|
||||
override def destinationDir = "src/test/java"
|
||||
|
||||
override def reservedWords = Set("abstract", "continue", "for", "new", "switch", "assert",
|
||||
"default", "if", "package", "synchronized", "boolean", "do", "goto", "private",
|
||||
"this", "break", "double", "implements", "protected", "throw", "byte", "else",
|
||||
@ -168,4 +168,12 @@ class BasicJavaGenerator extends BasicGenerator {
|
||||
throw new Exception("reserved word " + "\"" + word + "\" not allowed")
|
||||
else word
|
||||
}
|
||||
|
||||
// supporting classes
|
||||
// supporting classes
|
||||
override def supportingFiles =
|
||||
List(
|
||||
("apiInvoker.mustache", destinationDir + java.io.File.separator + invokerPackage.get.replaceAll("\\.", java.io.File.separator) + java.io.File.separator, "ApiInvoker.java"),
|
||||
("apiException.mustache", destinationDir + java.io.File.separator + invokerPackage.get.replaceAll("\\.", java.io.File.separator) + java.io.File.separator, "ApiException.java"),
|
||||
("pom.mustache", "generated-code/java", "pom.xml"))
|
||||
}
|
@ -62,7 +62,7 @@ class SwaggerSpecValidator(private val doc: ResourceListing,
|
||||
}
|
||||
|
||||
def validateResponseModels(subDocs: List[ApiListing]) = {
|
||||
val validModelNames = CoreUtils.extractAllModels2(subDocs).map(m => m._1).toSet
|
||||
val validModelNames = CoreUtils.extractAllModels(subDocs).map(m => m._1).toSet
|
||||
val requiredModels = new HashSet[String]
|
||||
subDocs.foreach(subDoc => {
|
||||
if (subDoc.apis != null) {
|
||||
|
@ -25,11 +25,11 @@ import com.wordnik.swagger.codegen.spec.SwaggerSpec._
|
||||
import scala.io.Source
|
||||
|
||||
object CoreUtils {
|
||||
def extractAllModels2(apis: List[ApiListing]): Map[String, Model] = {
|
||||
def extractAllModels(apis: List[ApiListing]): Map[String, Model] = {
|
||||
val modelObjects = new HashMap[String, Model]
|
||||
apis.foreach(api => {
|
||||
for ((nm, model) <- extractApiModels(api)) modelObjects += nm -> model
|
||||
if (api.models != null) api.models.foreach(model => modelObjects += model._1 -> model._2)
|
||||
api.models.foreach(model => modelObjects += model._1 -> model._2)
|
||||
})
|
||||
modelObjects.toMap
|
||||
}
|
||||
@ -38,49 +38,13 @@ object CoreUtils {
|
||||
val modelNames = new HashSet[String]
|
||||
modelNames += op.responseClass
|
||||
// POST, PUT, DELETE body
|
||||
if (op.parameters != null) {
|
||||
op.parameters.filter(p => p.paramType == "body")
|
||||
.foreach(p => modelNames += p.dataType)
|
||||
}
|
||||
op.parameters.filter(p => p.paramType == "body")
|
||||
.foreach(p => modelNames += p.dataType)
|
||||
val baseNames = (for (modelName <- (modelNames.toList))
|
||||
yield (extractBasePartFromType(modelName))).toSet
|
||||
baseNames.toSet
|
||||
}
|
||||
|
||||
def extractModelNames2(modelObjects: Map[String, Model], ep: Operation): Set[String] = {
|
||||
val modelNames = new HashSet[String]
|
||||
|
||||
modelNames += ep.responseClass
|
||||
// POST, PUT, DELETE body
|
||||
if (ep.parameters != null)
|
||||
ep.parameters.filter(p => p.paramType == "body")
|
||||
.foreach(p => modelNames += p.dataType)
|
||||
|
||||
val baseNames = (for (modelName <- (modelNames.toList))
|
||||
yield (extractBasePartFromType(modelName))).toSet
|
||||
|
||||
// get complex models from base
|
||||
val requiredModels = modelObjects.filter(obj => baseNames.contains(obj._1))
|
||||
|
||||
val subNames = new HashSet[String]
|
||||
// look inside top-level models
|
||||
requiredModels.map(model => {
|
||||
// add top level model
|
||||
subNames += model._1
|
||||
model._2.properties.foreach(prop => {
|
||||
val subObject = prop._2
|
||||
if (containers.contains(subObject.`type`)) {
|
||||
subObject.items match {
|
||||
case Some(item) => subNames += item.ref.getOrElse(item.`type`)
|
||||
case None =>
|
||||
}
|
||||
}
|
||||
else subNames += subObject.`type`
|
||||
})
|
||||
})
|
||||
subNames.toSet
|
||||
}
|
||||
|
||||
def extractBasePartFromType(datatype: String): String = {
|
||||
val ComplexTypeMatcher = ".*\\[(.*)\\].*".r
|
||||
datatype match {
|
||||
@ -93,21 +57,16 @@ object CoreUtils {
|
||||
val modelNames = new HashSet[String]
|
||||
val modelObjects = new HashMap[String, Model]
|
||||
// return types
|
||||
if(sd.apis != null){
|
||||
sd.apis.foreach(api => {
|
||||
if (api.operations != null)
|
||||
api.operations.foreach(op => {
|
||||
modelNames += op.responseClass
|
||||
// POST, PUT, DELETE body
|
||||
if(op.parameters != null)
|
||||
op.parameters.filter(p => p.paramType == "body")
|
||||
.foreach(p => modelNames += p.dataType)
|
||||
})
|
||||
sd.apis.foreach(api =>
|
||||
api.operations.foreach(op => {
|
||||
modelNames += op.responseClass
|
||||
// POST, PUT, DELETE body
|
||||
op.parameters.filter(p => p.paramType == "body")
|
||||
.foreach(p => modelNames += p.dataType)
|
||||
})
|
||||
}
|
||||
if(sd.models != null)
|
||||
for ((name, m) <- sd.models)
|
||||
modelObjects += name -> m
|
||||
)
|
||||
for ((name, m) <- sd.models)
|
||||
modelObjects += name -> m
|
||||
|
||||
// extract all base model names, strip away Containers like List[] and primitives
|
||||
val baseNames = (for (modelName <- (modelNames.toList filterNot primitives.contains))
|
||||
@ -118,40 +77,47 @@ object CoreUtils {
|
||||
|
||||
val subNames = new HashSet[String]
|
||||
// look inside top-level models
|
||||
requiredModels.map(model => {
|
||||
model._2.properties.foreach(prop => {
|
||||
val subObject = prop._2
|
||||
if (containers.contains(subObject.`type`)) {
|
||||
subObject.items match {
|
||||
case Some(subItem) => {
|
||||
val sn = subItem.ref.getOrElse(subItem.`type`)
|
||||
if(sn != null)
|
||||
subNames += sn
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
} else subNames += subObject.`type`
|
||||
})
|
||||
})
|
||||
recurseModels(requiredModels.toMap, modelObjects.toMap, subNames)
|
||||
|
||||
// look inside submodels
|
||||
modelObjects.filter(obj => subNames.contains(obj._1)).foreach(model => {
|
||||
model._2.properties.foreach(prop => {
|
||||
val subObject = prop._2
|
||||
if (containers.contains(subObject.`type`)) {
|
||||
subObject.items match {
|
||||
case Some(subItem) => {
|
||||
val sn = subItem.ref.getOrElse(subItem.`type`)
|
||||
if(sn != null)
|
||||
subNames += sn
|
||||
}
|
||||
case _ =>
|
||||
}
|
||||
} else subNames += subObject.`type`
|
||||
})
|
||||
})
|
||||
val subModels = modelObjects.filter(obj => subNames.contains(obj._1))
|
||||
val allModels = requiredModels ++ subModels
|
||||
allModels.filter(m => primitives.contains(m._1) == false).toMap
|
||||
}
|
||||
|
||||
def recurseModels(requiredModels: Map[String, Model], allModels: Map[String, Model], subNames: HashSet[String]) = {
|
||||
requiredModels.map(m => recurseModel(m._2, allModels, subNames))
|
||||
}
|
||||
|
||||
def recurseModel(model: Model, allModels: Map[String, Model], subNames: HashSet[String]): Unit = {
|
||||
model.properties.foreach(prop => {
|
||||
val subObject = prop._2
|
||||
val propertyName = containers.contains(subObject.`type`) match {
|
||||
case true => subObject.items match {
|
||||
case Some(subItem) => {
|
||||
Option(subItem.ref.getOrElse(subItem.`type`)) match {
|
||||
case Some(sn) => Some(sn)
|
||||
case _ => None
|
||||
}
|
||||
}
|
||||
case _ => None
|
||||
}
|
||||
case false => Some(subObject.`type`)
|
||||
}
|
||||
propertyName match {
|
||||
case Some(property) => subNames.contains(property) match {
|
||||
case false => {
|
||||
allModels.containsKey(property) match {
|
||||
case true => {
|
||||
recurseModel(allModels(property), allModels, subNames)
|
||||
}
|
||||
case false =>
|
||||
}
|
||||
subNames += property
|
||||
}
|
||||
case true =>
|
||||
}
|
||||
case None =>
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -233,7 +233,6 @@ class BasicScalaGeneratorTest extends FlatSpec with ShouldMatchers {
|
||||
m("returnBaseType") should be (Some("Pet"))
|
||||
|
||||
// problem here
|
||||
println("the operation has response class " + operation.responseClass)
|
||||
m("returnType") should be (Some("List[Pet]"))
|
||||
m("returnTypeIsPrimitive") should be (None)
|
||||
m("pathParams").asInstanceOf[List[_]].size should be (0)
|
||||
|
265
src/test/scala/CoreUtilsTest.scala
Normal file
265
src/test/scala/CoreUtilsTest.scala
Normal file
@ -0,0 +1,265 @@
|
||||
import com.wordnik.swagger.codegen.util.CoreUtils
|
||||
|
||||
import com.wordnik.swagger.model._
|
||||
import com.wordnik.swagger.codegen.util._
|
||||
|
||||
import org.junit.runner.RunWith
|
||||
import org.scalatest.junit.JUnitRunner
|
||||
import org.scalatest.FlatSpec
|
||||
import org.scalatest.matchers.ShouldMatchers
|
||||
|
||||
import org.json4s.jackson.JsonMethods._
|
||||
import org.json4s.jackson.Serialization.read
|
||||
|
||||
import scala.collection.mutable.LinkedHashMap
|
||||
|
||||
@RunWith(classOf[JUnitRunner])
|
||||
class CoreUtilsTest extends FlatSpec with ShouldMatchers {
|
||||
sys.props += "fileMap" -> "src/test/resources/petstore"
|
||||
|
||||
behavior of "CoreUtils"
|
||||
|
||||
it should "verify models are extracted" in {
|
||||
val resourceListing = ResourceExtractor.fetchListing("src/test/resources/petstore/resources.json")
|
||||
val apis = ApiExtractor.extractApiOperations("src/test/resources/petstore", resourceListing.apis)
|
||||
|
||||
val cu = CoreUtils.extractAllModels(apis)
|
||||
cu.size should be (5)
|
||||
|
||||
(cu.keys.toSet & Set("User", "Tag", "Pet", "Category", "Order")).size should be (5)
|
||||
}
|
||||
|
||||
it should "verify operation names" in {
|
||||
val resourceListing = ResourceExtractor.fetchListing("src/test/resources/petstore/resources.json")
|
||||
val apis = ApiExtractor.extractApiOperations("src/test/resources/petstore", resourceListing.apis)
|
||||
|
||||
val petApi = apis.filter(api => api.resourcePath == "/pet").head
|
||||
val eps = petApi.apis.map(api => (api.path, api)).toMap
|
||||
val ops = eps("/pet.{format}").operations.map(ep => (ep.nickname, ep)).toMap
|
||||
|
||||
ops.size should be (2)
|
||||
|
||||
(ops.keys.toSet & Set("addPet", "updatePet")).size should be (2)
|
||||
}
|
||||
|
||||
it should "find required models" in {
|
||||
val apis = CoreUtilsTest.sampleApis1
|
||||
val models = CoreUtils.extractApiModels(apis.head)
|
||||
models.size should be (5)
|
||||
}
|
||||
|
||||
it should "find required models from a nested list" in {
|
||||
val apis = CoreUtilsTest.sampleApis2
|
||||
val models = CoreUtils.extractApiModels(apis.head)
|
||||
models.size should be (5)
|
||||
}
|
||||
}
|
||||
|
||||
object CoreUtilsTest {
|
||||
implicit val formats = SwaggerSerializers.formats
|
||||
|
||||
def sampleApis1 = {
|
||||
parse("""
|
||||
[
|
||||
{
|
||||
"apiVersion": "0.2",
|
||||
"swaggerVersion": "1.1",
|
||||
"basePath": "http://api.helloreverb.com/api",
|
||||
"resourcePath": "/mysteries",
|
||||
"apis": [
|
||||
{
|
||||
"path": "/mysteries.{format}/{petId}",
|
||||
"description": "As the name suggests",
|
||||
"operations": [
|
||||
{
|
||||
"httpMethod": "GET",
|
||||
"summary": "You find amazing htings here",
|
||||
"responseClass": "DeepMystery",
|
||||
"nickname": "getMysteryById",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"description": "ID of mystery",
|
||||
"paramType": "path",
|
||||
"required": true,
|
||||
"allowMultiple": false,
|
||||
"dataType": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"models": {
|
||||
"MysteryList": {
|
||||
"id": "MysteryList",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "long"
|
||||
},
|
||||
"mysteries": {
|
||||
"items":{
|
||||
"$ref":"Mystery1"
|
||||
},
|
||||
"type":"Array"
|
||||
}
|
||||
}
|
||||
},
|
||||
"DeepMystery": {
|
||||
"id": "DeepMystery",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "Mystery1"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mystery1": {
|
||||
"id": "Mystery1",
|
||||
"properties": {
|
||||
"mystery2": {
|
||||
"type": "Mystery2"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mystery2": {
|
||||
"id": "Mystery2",
|
||||
"properties": {
|
||||
"mystery3": {
|
||||
"type": "Mystery3"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mystery3": {
|
||||
"id": "Mystery3",
|
||||
"properties": {
|
||||
"mystery4": {
|
||||
"type": "Mystery4"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mystery4": {
|
||||
"id": "Mystery4",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
""").extract[List[ApiListing]]
|
||||
}
|
||||
|
||||
def sampleApis2 = {
|
||||
parse("""
|
||||
[
|
||||
{
|
||||
"apiVersion": "0.2",
|
||||
"swaggerVersion": "1.1",
|
||||
"basePath": "http://api.helloreverb.com/api",
|
||||
"resourcePath": "/mysteries",
|
||||
"apis": [
|
||||
{
|
||||
"path": "/mysteries.{format}/{petId}",
|
||||
"description": "As the name suggests",
|
||||
"operations": [
|
||||
{
|
||||
"httpMethod": "GET",
|
||||
"summary": "You find amazing htings here",
|
||||
"responseClass": "MysteryList",
|
||||
"nickname": "getMysteryById",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "id",
|
||||
"description": "ID of mystery",
|
||||
"paramType": "path",
|
||||
"required": true,
|
||||
"allowMultiple": false,
|
||||
"dataType": "string"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"models": {
|
||||
"MysteryList": {
|
||||
"id": "MysteryList",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "long"
|
||||
},
|
||||
"mystery1": {
|
||||
"type":"Mystery1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mystery1": {
|
||||
"id": "Mystery1",
|
||||
"properties": {
|
||||
"mystery2": {
|
||||
"type": "Mystery2"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mystery2": {
|
||||
"id": "Mystery2",
|
||||
"properties": {
|
||||
"mystery3List": {
|
||||
"items": {
|
||||
"$ref": "Mystery3"
|
||||
},
|
||||
"type": "List"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mystery3": {
|
||||
"id": "Mystery3",
|
||||
"properties": {
|
||||
"mystery4": {
|
||||
"type": "Mystery4"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Mystery4": {
|
||||
"id": "Mystery4",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
""").extract[List[ApiListing]]
|
||||
}
|
||||
}
|
@ -59,7 +59,6 @@ class ResourceListingValidationTest extends FlatSpec with ShouldMatchers {
|
||||
"""
|
||||
parse(jsonString).extract[ResourceListing] match {
|
||||
case e: ResourceListing => {
|
||||
println(e)
|
||||
e.apis.size should be (2)
|
||||
}
|
||||
case _ => fail("didn't parse the underlying apis")
|
||||
|
@ -62,33 +62,3 @@ class ApiExtractorTest extends FlatSpec with ShouldMatchers {
|
||||
getOrderById.errorResponses.size should be (2)
|
||||
}
|
||||
}
|
||||
|
||||
@RunWith(classOf[JUnitRunner])
|
||||
class CoreUtilsTest extends FlatSpec with ShouldMatchers {
|
||||
sys.props += "fileMap" -> "src/test/resources/petstore"
|
||||
|
||||
behavior of "CoreUtils"
|
||||
|
||||
it should "verify models are extracted" in {
|
||||
val resourceListing = ResourceExtractor.fetchListing("src/test/resources/petstore/resources.json")
|
||||
val apis = ApiExtractor.extractApiOperations("src/test/resources/petstore", resourceListing.apis)
|
||||
|
||||
val cu = CoreUtils.extractAllModels2(apis)
|
||||
cu.size should be (5)
|
||||
|
||||
(cu.keys.toSet & Set("User", "Tag", "Pet", "Category", "Order")).size should be (5)
|
||||
}
|
||||
|
||||
it should "verify operation names" in {
|
||||
val resourceListing = ResourceExtractor.fetchListing("src/test/resources/petstore/resources.json")
|
||||
val apis = ApiExtractor.extractApiOperations("src/test/resources/petstore", resourceListing.apis)
|
||||
|
||||
val petApi = apis.filter(api => api.resourcePath == "/pet").head
|
||||
val eps = petApi.apis.map(api => (api.path, api)).toMap
|
||||
val ops = eps("/pet.{format}").operations.map(ep => (ep.nickname, ep)).toMap
|
||||
|
||||
ops.size should be (2)
|
||||
|
||||
(ops.keys.toSet & Set("addPet", "updatePet")).size should be (2)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user