forked from loafle/openapi-generator-original
Merge 'master' branch of 'swagger-codegen' into 'openapi-generator' (#327)
This commit is contained in:
@@ -472,6 +472,9 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
|
||||
String modifiedName = name.replaceAll("\\.", "");
|
||||
modifiedName = sanitizeKotlinSpecificNames(modifiedName);
|
||||
|
||||
// Camelize name of nested properties
|
||||
modifiedName = camelize(modifiedName);
|
||||
|
||||
if (reservedWords.contains(modifiedName)) {
|
||||
modifiedName = escapeReservedWord(modifiedName);
|
||||
}
|
||||
@@ -479,6 +482,12 @@ public abstract class AbstractKotlinCodegen extends DefaultCodegen implements Co
|
||||
return titleCase(modifiedName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toModelFilename(String name) {
|
||||
// Should be the same as the model name
|
||||
return toModelName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a strongly typed declaration for simple arrays of some type and arrays of arrays of some type.
|
||||
*
|
||||
|
||||
@@ -169,6 +169,13 @@
|
||||
(map (fn [[k v]] [k (normalize-param v)]))
|
||||
(into {})))
|
||||
|
||||
(defn default-to-json-mime
|
||||
"Default to JSON MIME if given */* MIME"
|
||||
[mime]
|
||||
(if (= mime "*/*")
|
||||
"application/json"
|
||||
mime))
|
||||
|
||||
(defn json-mime?
|
||||
"Check if the given MIME is a standard JSON MIME or :json."
|
||||
[mime]
|
||||
@@ -182,7 +189,7 @@
|
||||
[mimes]
|
||||
(-> (filter json-mime? mimes)
|
||||
first
|
||||
(or (first mimes))))
|
||||
(or (default-to-json-mime (first mimes)))))
|
||||
|
||||
(defn serialize
|
||||
"Serialize the given data according to content-type.
|
||||
|
||||
@@ -3,11 +3,11 @@ package {{packageName}}
|
||||
|
||||
{{#operations}}
|
||||
import (
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"context"
|
||||
{{#imports}} "{{import}}"
|
||||
{{/imports}}
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ package {{packageName}}
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"errors"
|
||||
@@ -20,7 +21,6 @@ import (
|
||||
"time"
|
||||
"unicode/utf8"
|
||||
|
||||
"context"
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
|
||||
@@ -9,6 +9,6 @@ import org.threeten.bp.LocalDateTime
|
||||
|
||||
{{#models}}
|
||||
{{#model}}
|
||||
{{#isEnum}}{{>enum_class}}{{/isEnum}}{{^isEnum}}{{>data_class}}{{/isEnum}}
|
||||
{{#isEnum}}{{>enum_class}}{{/isEnum}}{{^isEnum}}{{#isAlias}}typealias {{classname}} = {{dataType}}{{/isAlias}}{{^isAlias}}{{>data_class}}{{/isAlias}}{{/isEnum}}
|
||||
{{/model}}
|
||||
{{/models}}
|
||||
|
||||
@@ -60,17 +60,21 @@ from {{{packageName}}}.rest import ApiException
|
||||
from pprint import pprint
|
||||
{{#apiInfo}}{{#apis}}{{#-first}}{{#operations}}{{#operation}}{{#-first}}{{#hasAuthMethods}}{{#authMethods}}{{#isBasic}}
|
||||
# Configure HTTP basic authorization: {{{name}}}
|
||||
{{{packageName}}}.configuration.username = 'YOUR_USERNAME'
|
||||
{{{packageName}}}.configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}}
|
||||
configuration = {{{packageName}}}.Configuration()
|
||||
configuration.username = 'YOUR_USERNAME'
|
||||
configuration.password = 'YOUR_PASSWORD'{{/isBasic}}{{#isApiKey}}
|
||||
# Configure API key authorization: {{{name}}}
|
||||
{{{packageName}}}.configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY'
|
||||
configuration = {{{packageName}}}.Configuration()
|
||||
configuration.api_key['{{{keyParamName}}}'] = 'YOUR_API_KEY'
|
||||
# Uncomment below to setup prefix (e.g. Bearer) for API key, if needed
|
||||
# {{{packageName}}}.configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}}
|
||||
# configuration.api_key_prefix['{{{keyParamName}}}'] = 'Bearer'{{/isApiKey}}{{#isOAuth}}
|
||||
# Configure OAuth2 access token for authorization: {{{name}}}
|
||||
{{{packageName}}}.configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}}
|
||||
configuration = {{{packageName}}}.Configuration()
|
||||
configuration.access_token = 'YOUR_ACCESS_TOKEN'{{/isOAuth}}{{/authMethods}}
|
||||
{{/hasAuthMethods}}
|
||||
|
||||
# create an instance of the API class
|
||||
api_instance = {{{packageName}}}.{{{classname}}}()
|
||||
api_instance = {{{packageName}}}.{{{classname}}}({{{packageName}}}.ApiClient(configuration))
|
||||
{{#allParams}}{{paramName}} = {{{example}}} # {{{dataType}}} | {{{description}}}{{^required}} (optional){{/required}}{{#defaultValue}} (default to {{{.}}}){{/defaultValue}}
|
||||
{{/allParams}}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ chrono = { version = "0.4", features = ["serde"] }
|
||||
futures = "0.1"
|
||||
hyper = {version = "0.11", optional = true}
|
||||
hyper-tls = {version = "0.1.2", optional = true}
|
||||
swagger = "0.10.0"
|
||||
swagger = "0.12.1"
|
||||
|
||||
# Not required by example server.
|
||||
#
|
||||
|
||||
@@ -38,7 +38,7 @@ use std::collections::{HashMap, BTreeMap};
|
||||
#[allow(unused_imports)]
|
||||
use swagger;
|
||||
|
||||
use swagger::{Context, ApiError, XSpanId};
|
||||
use swagger::{ApiError, XSpanId, XSpanIdString, Has, AuthData};
|
||||
|
||||
use {Api{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
|
||||
{{operationId}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
@@ -67,8 +67,7 @@ fn into_base_path(input: &str, correct_scheme: Option<&'static str>) -> Result<S
|
||||
/// A client that implements the API by making HTTP calls out to a server.
|
||||
#[derive(Clone)]
|
||||
pub struct Client {
|
||||
hyper_client: Arc<Fn(&Handle) -> Box<hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=hyper::client::FutureResponse>> + Sync + Send>,
|
||||
handle: Arc<Handle>,
|
||||
hyper_client: Arc<Box<hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=hyper::client::FutureResponse>>>,
|
||||
base_path: String,
|
||||
}
|
||||
|
||||
@@ -173,25 +172,13 @@ impl Client {
|
||||
where
|
||||
C: hyper::client::Connect + hyper::client::Service,
|
||||
{
|
||||
let hyper_client = {
|
||||
move |handle: &Handle| -> Box<
|
||||
hyper::client::Service<
|
||||
Request = hyper::Request<hyper::Body>,
|
||||
Response = hyper::Response,
|
||||
Error = hyper::Error,
|
||||
Future = hyper::client::FutureResponse,
|
||||
>,
|
||||
> {
|
||||
let connector = connector_fn(handle);
|
||||
Box::new(hyper::Client::configure().connector(connector).build(
|
||||
handle,
|
||||
))
|
||||
}
|
||||
};
|
||||
let connector = connector_fn(&handle);
|
||||
let hyper_client = Box::new(hyper::Client::configure().connector(connector).build(
|
||||
&handle,
|
||||
));
|
||||
|
||||
Ok(Client {
|
||||
hyper_client: Arc::new(hyper_client),
|
||||
handle: Arc::new(handle),
|
||||
base_path: into_base_path(base_path, protocol)?,
|
||||
})
|
||||
}
|
||||
@@ -205,22 +192,21 @@ impl Client {
|
||||
/// The reason for this function's existence is to support legacy test code, which did mocking at the hyper layer.
|
||||
/// This is not a recommended way to write new tests. If other reasons are found for using this function, they
|
||||
/// should be mentioned here.
|
||||
pub fn try_new_with_hyper_client(hyper_client: Arc<Fn(&Handle) -> Box<hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=hyper::client::FutureResponse>> + Sync + Send>,
|
||||
pub fn try_new_with_hyper_client(hyper_client: Arc<Box<hyper::client::Service<Request=hyper::Request<hyper::Body>, Response=hyper::Response, Error=hyper::Error, Future=hyper::client::FutureResponse>>>,
|
||||
handle: Handle,
|
||||
base_path: &str)
|
||||
-> Result<Client, ClientInitError>
|
||||
{
|
||||
Ok(Client {
|
||||
hyper_client: hyper_client,
|
||||
handle: Arc::new(handle),
|
||||
base_path: into_base_path(base_path, None)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Api for Client {
|
||||
impl<C> Api<C> for Client where C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<AuthData>>{{/hasAuthMethods}}{
|
||||
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
|
||||
fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, param_{{paramName}}: {{^required}}{{#isFile}}Box<Future<Item={{/isFile}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &Context) -> Box<Future<Item={{operationId}}Response, Error=ApiError>> {
|
||||
fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, param_{{paramName}}: {{^required}}{{#isFile}}Box<Future<Item={{/isFile}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &C) -> Box<Future<Item={{operationId}}Response, Error=ApiError>> {
|
||||
{{#queryParams}}{{#-first}}
|
||||
// Query parameters
|
||||
{{/-first}}{{#required}} let query_{{paramName}} = format!("{{baseName}}={{=<% %>=}}{<% paramName %>}<%={{ }}=%>&", {{paramName}}=param_{{paramName}}{{#isListContainer}}.join(","){{/isListContainer}}{{^isListContainer}}.to_string(){{/isListContainer}});
|
||||
@@ -306,9 +292,9 @@ impl Api for Client {
|
||||
|
||||
request.headers_mut().set(ContentType(mimetypes::requests::{{#vendorExtensions}}{{uppercase_operation_id}}{{/vendorExtensions}}.clone()));
|
||||
{{/bodyParam}}
|
||||
context.x_span_id.as_ref().map(|header| request.headers_mut().set(XSpanId(header.clone())));
|
||||
{{#authMethods}}{{#isBasic}} context.auth_data.as_ref().map(|auth_data| {
|
||||
if let &swagger::AuthData::Basic(ref basic_header) = auth_data {
|
||||
request.headers_mut().set(XSpanId((context as &Has<XSpanIdString>).get().0.clone()));
|
||||
{{#authMethods}}{{#isBasic}} (context as &Has<Option<AuthData>>).get().as_ref().map(|auth_data| {
|
||||
if let &AuthData::Basic(ref basic_header) = auth_data {
|
||||
request.headers_mut().set(hyper::header::Authorization(
|
||||
basic_header.clone(),
|
||||
))
|
||||
@@ -326,8 +312,7 @@ impl Api for Client {
|
||||
request.set_body(body_string.into_bytes());
|
||||
{{/hasFile}}{{/vendorExtensions}}
|
||||
|
||||
let hyper_client = (self.hyper_client)(&*self.handle);
|
||||
Box::new(hyper_client.call(request)
|
||||
Box::new(self.hyper_client.call(request)
|
||||
.map_err(|e| ApiError(format!("No response received: {}", e)))
|
||||
.and_then(|mut response| {
|
||||
match response.status().as_u16() {
|
||||
|
||||
@@ -4,12 +4,15 @@ extern crate {{externCrateName}};
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate futures;
|
||||
#[allow(unused_extern_crates)]
|
||||
#[macro_use]
|
||||
extern crate swagger;
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate uuid;
|
||||
extern crate clap;
|
||||
extern crate tokio_core;
|
||||
|
||||
use swagger::{ContextBuilder, EmptyContext, XSpanIdString, Has, Push, AuthData};
|
||||
|
||||
#[allow(unused_imports)]
|
||||
use futures::{Future, future, Stream, stream};
|
||||
use tokio_core::reactor;
|
||||
@@ -60,15 +63,16 @@ fn main() {
|
||||
.expect("Failed to create HTTP client")
|
||||
};
|
||||
|
||||
// Using a non-default `Context` is not required; this is just an example!
|
||||
let client = client.with_context({{externCrateName}}::Context::new_with_span_id(self::uuid::Uuid::new_v4().to_string()));
|
||||
let context: make_context_ty!(ContextBuilder, EmptyContext, Option<AuthData>, XSpanIdString) =
|
||||
make_context!(ContextBuilder, EmptyContext, None, XSpanIdString(self::uuid::Uuid::new_v4().to_string()));
|
||||
let client = client.with_context(context);
|
||||
|
||||
match matches.value_of("operation") {
|
||||
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
|
||||
{{#vendorExtensions}}{{#noClientExample}}// Disabled because there's no example.
|
||||
// {{/noClientExample}}Some("{{operationId}}") => {
|
||||
{{#noClientExample}}// {{/noClientExample}} let result = core.run(client.{{operation_id}}{{/vendorExtensions}}({{#allParams}}{{^-first}}, {{/-first}}{{#vendorExtensions}}{{{example}}}{{/vendorExtensions}}{{/allParams}}));
|
||||
{{#vendorExtensions}}{{#noClientExample}}// {{/noClientExample}}{{/vendorExtensions}} println!("{:?} (X-Span-ID: {:?})", result, client.context().x_span_id.clone().unwrap_or(String::from("<none>")));
|
||||
{{#vendorExtensions}}{{#noClientExample}}// {{/noClientExample}}{{/vendorExtensions}} println!("{:?} (X-Span-ID: {:?})", result, (client.context() as &Has<XSpanIdString>).get().clone());
|
||||
{{#vendorExtensions}}{{#noClientExample}}// {{/noClientExample}}{{/vendorExtensions}} },
|
||||
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
_ => {
|
||||
|
||||
@@ -29,6 +29,7 @@ use hyper::server::Http;
|
||||
use tokio_proto::TcpServer;
|
||||
use clap::{App, Arg};
|
||||
use swagger::auth::AllowAllAuthenticator;
|
||||
use swagger::EmptyContext;
|
||||
|
||||
mod server_lib;
|
||||
|
||||
@@ -54,9 +55,9 @@ fn main() {
|
||||
.get_matches();
|
||||
|
||||
let service_fn =
|
||||
{{externCrateName}}::server::auth::NewService::new(
|
||||
{{externCrateName}}::server::auth::NewService::<_, EmptyContext>::new(
|
||||
AllowAllAuthenticator::new(
|
||||
server_lib::NewService,
|
||||
server_lib::NewService::new(),
|
||||
"cosmo"
|
||||
)
|
||||
);
|
||||
|
||||
@@ -8,19 +8,31 @@ mod errors {
|
||||
|
||||
pub use self::errors::*;
|
||||
use std::io;
|
||||
use std::clone::Clone;
|
||||
use std::marker::PhantomData;
|
||||
use hyper;
|
||||
use {{externCrateName}};
|
||||
use swagger::{Has, XSpanIdString};
|
||||
use swagger::auth::Authorization;
|
||||
|
||||
pub struct NewService;
|
||||
pub struct NewService<C>{
|
||||
marker: PhantomData<C>
|
||||
}
|
||||
|
||||
impl hyper::server::NewService for NewService {
|
||||
type Request = (hyper::Request, {{externCrateName}}::Context);
|
||||
impl<C> NewService<C>{
|
||||
pub fn new() -> Self {
|
||||
NewService{marker:PhantomData}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> hyper::server::NewService for NewService<C> where C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + Clone + 'static {
|
||||
type Request = (hyper::Request, C);
|
||||
type Response = hyper::Response;
|
||||
type Error = hyper::Error;
|
||||
type Instance = {{externCrateName}}::server::Service<server::Server>;
|
||||
type Instance = {{externCrateName}}::server::Service<server::Server<C>, C>;
|
||||
|
||||
/// Instantiate a new server.
|
||||
fn new_service(&self) -> io::Result<Self::Instance> {
|
||||
Ok({{externCrateName}}::server::Service::new(server::Server))
|
||||
Ok({{externCrateName}}::server::Service::new(server::Server::new()))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,23 +7,33 @@ use chrono;
|
||||
{{#apiHasFile}}use futures::Stream;{{/apiHasFile}}
|
||||
use std::collections::HashMap;
|
||||
{{#apiHasFile}}use std::io::Error;{{/apiHasFile}}
|
||||
use std::marker::PhantomData;
|
||||
{{#apiUsesUuid}}use uuid;{{/apiUsesUuid}}
|
||||
use swagger;
|
||||
use swagger::{Has, XSpanIdString};
|
||||
|
||||
use {{externCrateName}}::{Api, ApiError, Context{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
|
||||
use {{externCrateName}}::{Api, ApiError{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
|
||||
{{operationId}}Response{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
};
|
||||
use {{externCrateName}}::models;
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Server;
|
||||
pub struct Server<C> {
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl Api for Server {
|
||||
impl<C> Server<C> {
|
||||
pub fn new() -> Self {
|
||||
Server{marker: PhantomData}
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> Api<C> for Server<C> where C: Has<XSpanIdString>{
|
||||
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
|
||||
{{#summary}} /// {{{summary}}}{{/summary}}
|
||||
fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box<Future<Item={{/isFile}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &Context) -> Box<Future<Item={{operationId}}Response, Error=ApiError>> {
|
||||
fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box<Future<Item={{/isFile}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &C) -> Box<Future<Item={{operationId}}Response, Error=ApiError>> {
|
||||
let context = context.clone();
|
||||
println!("{{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}({{#allParams}}{{^isFile}}{{#vendorExtensions}}{{{formatString}}}{{/vendorExtensions}}{{#hasMore}}, {{/hasMore}}{{/isFile}}{{/allParams}}) - X-Span-ID: {:?}"{{#allParams}}{{^isFile}}, {{paramName}}{{/isFile}}{{/allParams}}, context.x_span_id.unwrap_or(String::from("<none>")).clone());{{#allParams}}{{#isFile}}
|
||||
println!("{{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}({{#allParams}}{{^isFile}}{{#vendorExtensions}}{{{formatString}}}{{/vendorExtensions}}{{#hasMore}}, {{/hasMore}}{{/isFile}}{{/allParams}}) - X-Span-ID: {:?}"{{#allParams}}{{^isFile}}, {{paramName}}{{/isFile}}{{/allParams}}, context.get().0.clone());{{#allParams}}{{#isFile}}
|
||||
let _ = {{paramName}}; //Suppresses unused param warning{{/isFile}}{{/allParams}}
|
||||
Box::new(futures::failed("Generic failure".into()))
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ pub use futures::Future;
|
||||
#[cfg(any(feature = "client", feature = "server"))]
|
||||
mod mimetypes;
|
||||
|
||||
pub use swagger::{ApiError, Context, ContextWrapper};
|
||||
pub use swagger::{ApiError, ContextWrapper};
|
||||
|
||||
pub const BASE_PATH: &'static str = "{{basePathWithoutHost}}";
|
||||
pub const API_VERSION: &'static str = "{{appVersion}}";
|
||||
@@ -48,10 +48,10 @@ pub enum {{operationId}}Response {
|
||||
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
|
||||
/// API
|
||||
pub trait Api {
|
||||
pub trait Api<C> {
|
||||
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
|
||||
{{#summary}} /// {{{summary}}}{{/summary}}
|
||||
fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box<Future<Item={{/isFile}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &Context) -> Box<Future<Item={{operationId}}Response, Error=ApiError>>;
|
||||
fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box<Future<Item={{/isFile}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}, context: &C) -> Box<Future<Item={{operationId}}Response, Error=ApiError>>;
|
||||
{{/operation}}{{/operations}}{{/apis}}{{/apiInfo}}
|
||||
}
|
||||
|
||||
@@ -64,18 +64,18 @@ pub trait ApiNoContext {
|
||||
}
|
||||
|
||||
/// Trait to extend an API to make it easy to bind it to a context.
|
||||
pub trait ContextWrapperExt<'a> where Self: Sized {
|
||||
pub trait ContextWrapperExt<'a, C> where Self: Sized {
|
||||
/// Binds this API to a context.
|
||||
fn with_context(self: &'a Self, context: Context) -> ContextWrapper<'a, Self>;
|
||||
fn with_context(self: &'a Self, context: C) -> ContextWrapper<'a, Self, C>;
|
||||
}
|
||||
|
||||
impl<'a, T: Api + Sized> ContextWrapperExt<'a> for T {
|
||||
fn with_context(self: &'a T, context: Context) -> ContextWrapper<'a, T> {
|
||||
ContextWrapper::<T>::new(self, context)
|
||||
impl<'a, T: Api<C> + Sized, C> ContextWrapperExt<'a, C> for T {
|
||||
fn with_context(self: &'a T, context: C) -> ContextWrapper<'a, T, C> {
|
||||
ContextWrapper::<T, C>::new(self, context)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Api> ApiNoContext for ContextWrapper<'a, T> {
|
||||
impl<'a, T: Api<C>, C> ApiNoContext for ContextWrapper<'a, T, C> {
|
||||
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
|
||||
{{#summary}} /// {{{summary}}}{{/summary}}
|
||||
fn {{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}(&self{{#allParams}}, {{paramName}}: {{^required}}{{#isFile}}Box<Future<Item={{/isFile}}Option<{{/required}}{{#isListContainer}}&{{/isListContainer}}{{{dataType}}}{{^required}}>{{#isFile}}, Error=Error> + Send>{{/isFile}}{{/required}}{{/allParams}}) -> Box<Future<Item={{operationId}}Response, Error=ApiError>> {
|
||||
|
||||
@@ -1,25 +1,47 @@
|
||||
use std::io;
|
||||
use std::marker::PhantomData;
|
||||
use std::default::Default;
|
||||
use hyper;
|
||||
use hyper::{Request, Response, Error, StatusCode};
|
||||
use server::url::form_urlencoded;
|
||||
use swagger::auth::{Authorization, AuthData, Scopes};
|
||||
use swagger::{Has, Pop, Push, XSpanIdString};
|
||||
use Api;
|
||||
|
||||
pub struct NewService<T> where T: hyper::server::NewService<Request=(Request,Option<AuthData>), Response=Response, Error=Error> {
|
||||
pub struct NewService<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
|
||||
{
|
||||
inner: T,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<T> NewService<T> where T: hyper::server::NewService<Request=(Request,Option<AuthData>), Response=Response, Error=Error> + 'static {
|
||||
pub fn new(inner: T) -> NewService<T> {
|
||||
NewService{inner}
|
||||
impl<T, C> NewService<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error> + 'static,
|
||||
{
|
||||
pub fn new(inner: T) -> NewService<T, C> {
|
||||
NewService {
|
||||
inner,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> hyper::server::NewService for NewService<T> where T: hyper::server::NewService<Request=(Request,Option<AuthData>), Response=Response, Error=Error> + 'static {
|
||||
impl<T, C> hyper::server::NewService for NewService<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::NewService<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error> + 'static,
|
||||
{
|
||||
type Request = Request;
|
||||
type Response = Response;
|
||||
type Error = Error;
|
||||
type Instance = Service<T::Instance>;
|
||||
type Instance = Service<T::Instance, C>;
|
||||
|
||||
fn new_service(&self) -> Result<Self::Instance, io::Error> {
|
||||
self.inner.new_service().map(|s| Service::new(s))
|
||||
@@ -27,23 +49,44 @@ impl<T> hyper::server::NewService for NewService<T> where T: hyper::server::NewS
|
||||
}
|
||||
|
||||
/// Middleware to extract authentication data from request
|
||||
pub struct Service<T> where T: hyper::server::Service<Request=(Request,Option<AuthData>), Response=Response, Error=Error> {
|
||||
pub struct Service<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
|
||||
{
|
||||
inner: T,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<T> Service<T> where T: hyper::server::Service<Request=(Request,Option<AuthData>), Response=Response, Error=Error> {
|
||||
pub fn new(inner: T) -> Service<T> {
|
||||
Service{inner}
|
||||
impl<T, C> Service<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
|
||||
{
|
||||
pub fn new(inner: T) -> Service<T, C> {
|
||||
Service {
|
||||
inner,
|
||||
marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> hyper::server::Service for Service<T> where T: hyper::server::Service<Request=(Request,Option<AuthData>), Response=Response, Error=Error> {
|
||||
impl<T, C> hyper::server::Service for Service<T, C>
|
||||
where
|
||||
C: Default + Push<XSpanIdString>,
|
||||
C::Result: Push<Option<AuthData>>,
|
||||
T: hyper::server::Service<Request = (Request, <C::Result as Push<Option<AuthData>>>::Result), Response = Response, Error = Error>,
|
||||
{
|
||||
type Request = Request;
|
||||
type Response = Response;
|
||||
type Error = Error;
|
||||
type Future = T::Future;
|
||||
|
||||
fn call(&self, req: Self::Request) -> Self::Future {
|
||||
let context = C::default().push(XSpanIdString::get_or_generate(&req));
|
||||
|
||||
{{#authMethods}}
|
||||
{{#isBasic}}
|
||||
{
|
||||
@@ -51,7 +94,8 @@ impl<T> hyper::server::Service for Service<T> where T: hyper::server::Service<Re
|
||||
use std::ops::Deref;
|
||||
if let Some(basic) = req.headers().get::<Authorization<Basic>>().cloned() {
|
||||
let auth_data = AuthData::Basic(basic.deref().clone());
|
||||
return self.inner.call((req, Some(auth_data)));
|
||||
let context = context.push(Some(auth_data));
|
||||
return self.inner.call((req, context));
|
||||
}
|
||||
}
|
||||
{{/isBasic}}
|
||||
@@ -61,7 +105,8 @@ impl<T> hyper::server::Service for Service<T> where T: hyper::server::Service<Re
|
||||
use std::ops::Deref;
|
||||
if let Some(bearer) = req.headers().get::<Authorization<Bearer>>().cloned() {
|
||||
let auth_data = AuthData::Bearer(bearer.deref().clone());
|
||||
return self.inner.call((req, Some(auth_data)));
|
||||
let context = context.push(Some(auth_data));
|
||||
return self.inner.call((req, context));
|
||||
}
|
||||
}
|
||||
{{/isOAuth}}
|
||||
@@ -71,7 +116,8 @@ impl<T> hyper::server::Service for Service<T> where T: hyper::server::Service<Re
|
||||
header! { (ApiKey{{-index}}, "{{keyParamName}}") => [String] }
|
||||
if let Some(header) = req.headers().get::<ApiKey{{-index}}>().cloned() {
|
||||
let auth_data = AuthData::ApiKey(header.0);
|
||||
return self.inner.call((req, Some(auth_data)));
|
||||
let context = context.push(Some(auth_data));
|
||||
return self.inner.call((req, context));
|
||||
}
|
||||
}
|
||||
{{/isKeyInHeader}}
|
||||
@@ -83,13 +129,15 @@ impl<T> hyper::server::Service for Service<T> where T: hyper::server::Service<Re
|
||||
.nth(0);
|
||||
if let Some(key) = key {
|
||||
let auth_data = AuthData::ApiKey(key);
|
||||
return self.inner.call((req, Some(auth_data)));
|
||||
let context = context.push(Some(auth_data));
|
||||
return self.inner.call((req, context));
|
||||
}
|
||||
}
|
||||
{{/isKeyInQuery}}
|
||||
{{/isApiKey}}
|
||||
{{/authMethods}}
|
||||
|
||||
return self.inner.call((req, None));
|
||||
let context = context.push(None);
|
||||
return self.inner.call((req, context));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ extern crate url;
|
||||
|
||||
{{#apiUsesUuid}}use uuid;{{/apiUsesUuid}}
|
||||
use std::sync::Arc;
|
||||
use std::marker::PhantomData;
|
||||
use futures::{Future, future, Stream, stream};
|
||||
use hyper;
|
||||
use hyper::{Request, Response, Error, StatusCode};
|
||||
@@ -35,7 +36,7 @@ use std::io;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
pub use swagger::auth::Authorization;
|
||||
use swagger::{ApiError, Context, XSpanId};
|
||||
use swagger::{ApiError, XSpanId, XSpanIdString, Has};
|
||||
use swagger::auth::Scopes;
|
||||
|
||||
use {Api{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}},
|
||||
@@ -68,39 +69,56 @@ mod paths {
|
||||
{{/pathSet}}
|
||||
}
|
||||
|
||||
pub struct NewService<T> {
|
||||
pub struct NewService<T, C> {
|
||||
api_impl: Arc<T>,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<T> NewService<T> where T: Api + Clone + 'static {
|
||||
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> NewService<T> {
|
||||
NewService{api_impl: api_impl.into()}
|
||||
impl<T, C> NewService<T, C>
|
||||
where
|
||||
T: Api<C> + Clone + 'static,
|
||||
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static
|
||||
{
|
||||
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> NewService<T, C> {
|
||||
NewService{api_impl: api_impl.into(), marker: PhantomData}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> hyper::server::NewService for NewService<T> where T: Api + Clone + 'static {
|
||||
type Request = (Request, Context);
|
||||
impl<T, C> hyper::server::NewService for NewService<T, C>
|
||||
where
|
||||
T: Api<C> + Clone + 'static,
|
||||
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static
|
||||
{
|
||||
type Request = (Request, C);
|
||||
type Response = Response;
|
||||
type Error = Error;
|
||||
type Instance = Service<T>;
|
||||
type Instance = Service<T, C>;
|
||||
|
||||
fn new_service(&self) -> Result<Self::Instance, io::Error> {
|
||||
Ok(Service::new(self.api_impl.clone()))
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Service<T> {
|
||||
pub struct Service<T, C> {
|
||||
api_impl: Arc<T>,
|
||||
marker: PhantomData<C>,
|
||||
}
|
||||
|
||||
impl<T> Service<T> where T: Api + Clone + 'static {
|
||||
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> Service<T> {
|
||||
Service{api_impl: api_impl.into()}
|
||||
impl<T, C> Service<T, C>
|
||||
where
|
||||
T: Api<C> + Clone + 'static,
|
||||
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static {
|
||||
pub fn new<U: Into<Arc<T>>>(api_impl: U) -> Service<T, C> {
|
||||
Service{api_impl: api_impl.into(), marker: PhantomData}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> hyper::server::Service for Service<T> where T: Api + Clone + 'static {
|
||||
type Request = (Request, Context);
|
||||
impl<T, C> hyper::server::Service for Service<T, C>
|
||||
where
|
||||
T: Api<C> + Clone + 'static,
|
||||
C: Has<XSpanIdString> {{#hasAuthMethods}}+ Has<Option<Authorization>>{{/hasAuthMethods}} + 'static
|
||||
{
|
||||
type Request = (Request, C);
|
||||
type Response = Response;
|
||||
type Error = Error;
|
||||
type Future = Box<Future<Item=Response, Error=Error>>;
|
||||
@@ -113,14 +131,11 @@ impl<T> hyper::server::Service for Service<T> where T: Api + Clone + 'static {
|
||||
{{#apiInfo}}{{#apis}}{{#operations}}{{#operation}}
|
||||
// {{operationId}} - {{httpMethod}} {{path}}
|
||||
&hyper::Method::{{vendorExtensions.HttpMethod}} if path.matched(paths::ID_{{vendorExtensions.PATH_ID}}) => {
|
||||
if context.x_span_id.is_none() {
|
||||
context.x_span_id = Some(headers.get::<XSpanId>().map(XSpanId::to_string).unwrap_or_else(|| self::uuid::Uuid::new_v4().to_string()));
|
||||
}
|
||||
{{#hasAuthMethods}}
|
||||
{
|
||||
let authorization = match context.authorization.as_ref() {
|
||||
Some(authorization) => authorization,
|
||||
None => return Box::new(future::ok(Response::new()
|
||||
let authorization = match (&context as &Has<Option<Authorization>>).get() {
|
||||
&Some(ref authorization) => authorization,
|
||||
&None => return Box::new(future::ok(Response::new()
|
||||
.with_status(StatusCode::Forbidden)
|
||||
.with_body("Unauthenticated"))),
|
||||
};
|
||||
@@ -304,7 +319,7 @@ impl<T> hyper::server::Service for Service<T> where T: Api + Clone + 'static {
|
||||
{{^required}}{{#isFile}} let param_{{paramName}} = Box::new(future::ok(param_{{paramName}}));{{/isFile}}{{/required}}
|
||||
{{/formParams}}
|
||||
{{/hasFile}}{{^hasFile}}
|
||||
Box::new(({
|
||||
Box::new({
|
||||
{{
|
||||
{{#formParams}}{{#-first}}
|
||||
// Form parameters
|
||||
@@ -315,7 +330,7 @@ impl<T> hyper::server::Service for Service<T> where T: Api + Clone + 'static {
|
||||
Box::new(api_impl.{{#vendorExtensions}}{{operation_id}}{{/vendorExtensions}}({{#allParams}}param_{{paramName}}{{#isListContainer}}.as_ref(){{/isListContainer}}, {{/allParams}}&context)
|
||||
.then(move |result| {
|
||||
let mut response = Response::new();
|
||||
context.x_span_id.as_ref().map(|header| response.headers_mut().set(XSpanId(header.clone())));
|
||||
response.headers_mut().set(XSpanId((&context as &Has<XSpanIdString>).get().0.to_string()));
|
||||
{{#bodyParams}}{{#vendorExtensions}}{{^consumesPlainText}}
|
||||
if !unused_elements.is_empty() {
|
||||
response.headers_mut().set(Warning(format!("Ignoring unknown fields in body: {:?}", unused_elements)));
|
||||
@@ -410,7 +425,7 @@ impl<T> hyper::server::Service for Service<T> where T: Api + Clone + 'static {
|
||||
))
|
||||
{{^bodyParams}}{{#vendorExtensions}}{{^hasFile}}
|
||||
}}
|
||||
})) as Box<Future<Item=Response, Error=Error>>
|
||||
}) as Box<Future<Item=Response, Error=Error>>
|
||||
{{/hasFile}}{{#hasFile}}
|
||||
as Box<Future<Item=Response, Error=Error>>
|
||||
},
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
package org.openapitools.codegen.kotlin;
|
||||
|
||||
import io.swagger.v3.oas.models.media.ArraySchema;
|
||||
import io.swagger.v3.oas.models.media.DateTimeSchema;
|
||||
import io.swagger.v3.oas.models.media.IntegerSchema;
|
||||
import io.swagger.v3.oas.models.media.MapSchema;
|
||||
import io.swagger.v3.oas.models.media.ObjectSchema;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import io.swagger.v3.oas.models.media.StringSchema;
|
||||
|
||||
import org.openapitools.codegen.CodegenModel;
|
||||
import org.openapitools.codegen.CodegenProperty;
|
||||
import org.openapitools.codegen.DefaultCodegen;
|
||||
import org.openapitools.codegen.languages.KotlinClientCodegen;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.DataProvider;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
@SuppressWarnings("static-method")
|
||||
public class KotlinClientCodegenModelTest {
|
||||
|
||||
private Schema getArrayTestSchema() {
|
||||
return new ObjectSchema()
|
||||
.description("a sample model")
|
||||
.addProperties("id", new IntegerSchema().format("int64"))
|
||||
.addProperties("examples", new ArraySchema().items(new StringSchema()))
|
||||
.addRequiredItem("id");
|
||||
}
|
||||
|
||||
private Schema getSimpleSchema() {
|
||||
return new ObjectSchema()
|
||||
.description("a sample model")
|
||||
.addProperties("id", new IntegerSchema().format("int64"))
|
||||
.addProperties("name", new StringSchema())
|
||||
.addProperties("createdAt", new DateTimeSchema())
|
||||
.addRequiredItem("id")
|
||||
.addRequiredItem("name");
|
||||
}
|
||||
|
||||
private Schema getMapSchema() {
|
||||
return new ObjectSchema()
|
||||
.description("a sample model")
|
||||
.addProperties("mapping", new MapSchema()
|
||||
.additionalProperties(new StringSchema()));
|
||||
}
|
||||
|
||||
private Schema getComplexSchema() {
|
||||
return new ObjectSchema()
|
||||
.description("a sample model")
|
||||
.addProperties("child", new ObjectSchema().$ref("#/components/schemas/Child"));
|
||||
}
|
||||
|
||||
@Test(description = "convert a simple model")
|
||||
public void simpleModelTest() {
|
||||
final Schema schema = getSimpleSchema();
|
||||
final DefaultCodegen codegen = new KotlinClientCodegen();
|
||||
|
||||
final CodegenModel cm = codegen.fromModel("sample", schema);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a sample model");
|
||||
Assert.assertEquals(cm.vars.size(), 3);
|
||||
|
||||
final CodegenProperty property1 = cm.vars.get(0);
|
||||
Assert.assertEquals(property1.baseName, "id");
|
||||
Assert.assertEquals(property1.datatype, "kotlin.Long");
|
||||
Assert.assertEquals(property1.name, "id");
|
||||
Assert.assertEquals(property1.defaultValue, "null");
|
||||
Assert.assertEquals(property1.baseType, "kotlin.Long");
|
||||
Assert.assertTrue(property1.hasMore);
|
||||
Assert.assertTrue(property1.required);
|
||||
Assert.assertTrue(property1.isPrimitiveType);
|
||||
Assert.assertTrue(property1.isNotContainer);
|
||||
|
||||
final CodegenProperty property2 = cm.vars.get(1);
|
||||
Assert.assertEquals(property2.baseName, "name");
|
||||
Assert.assertEquals(property2.datatype, "kotlin.String");
|
||||
Assert.assertEquals(property2.name, "name");
|
||||
Assert.assertEquals(property2.defaultValue, "null");
|
||||
Assert.assertEquals(property2.baseType, "kotlin.String");
|
||||
Assert.assertTrue(property2.hasMore);
|
||||
Assert.assertTrue(property2.required);
|
||||
Assert.assertTrue(property2.isPrimitiveType);
|
||||
Assert.assertTrue(property2.isNotContainer);
|
||||
|
||||
final CodegenProperty property3 = cm.vars.get(2);
|
||||
Assert.assertEquals(property3.baseName, "createdAt");
|
||||
Assert.assertEquals(property3.datatype, "java.time.LocalDateTime");
|
||||
Assert.assertEquals(property3.name, "createdAt");
|
||||
Assert.assertEquals(property3.defaultValue, "null");
|
||||
Assert.assertEquals(property3.baseType, "java.time.LocalDateTime");
|
||||
Assert.assertFalse(property3.hasMore);
|
||||
Assert.assertFalse(property3.required);
|
||||
Assert.assertTrue(property3.isNotContainer);
|
||||
}
|
||||
|
||||
@Test(description = "convert a simple model: threetenbp")
|
||||
public void selectDateLibraryAsThreetenbp() {
|
||||
final Schema schema = getSimpleSchema();
|
||||
final KotlinClientCodegen codegen = new KotlinClientCodegen();
|
||||
codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.THREETENBP.value);
|
||||
codegen.processOpts();
|
||||
|
||||
final CodegenModel cm = codegen.fromModel("sample", schema);
|
||||
|
||||
final CodegenProperty property3 = cm.vars.get(2);
|
||||
Assert.assertEquals(property3.baseName, "createdAt");
|
||||
Assert.assertEquals(property3.datatype, "org.threeten.bp.LocalDateTime");
|
||||
Assert.assertEquals(property3.name, "createdAt");
|
||||
Assert.assertEquals(property3.defaultValue, "null");
|
||||
Assert.assertEquals(property3.baseType, "org.threeten.bp.LocalDateTime");
|
||||
Assert.assertFalse(property3.hasMore);
|
||||
Assert.assertFalse(property3.required);
|
||||
Assert.assertTrue(property3.isNotContainer);
|
||||
}
|
||||
|
||||
@Test(description = "convert a simple model: date string")
|
||||
public void selectDateLibraryAsString() {
|
||||
final Schema schema = getSimpleSchema();
|
||||
final KotlinClientCodegen codegen = new KotlinClientCodegen();
|
||||
codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.STRING.value);
|
||||
codegen.processOpts();
|
||||
|
||||
final CodegenModel cm = codegen.fromModel("sample", schema);
|
||||
|
||||
final CodegenProperty property3 = cm.vars.get(2);
|
||||
Assert.assertEquals(property3.baseName, "createdAt");
|
||||
Assert.assertEquals(property3.datatype, "kotlin.String");
|
||||
Assert.assertEquals(property3.name, "createdAt");
|
||||
Assert.assertEquals(property3.defaultValue, "null");
|
||||
Assert.assertEquals(property3.baseType, "kotlin.String");
|
||||
Assert.assertFalse(property3.hasMore);
|
||||
Assert.assertFalse(property3.required);
|
||||
Assert.assertTrue(property3.isNotContainer);
|
||||
}
|
||||
|
||||
@Test(description = "convert a simple model: date java8")
|
||||
public void selectDateLibraryAsJava8() {
|
||||
final Schema schema = getSimpleSchema();
|
||||
final KotlinClientCodegen codegen = new KotlinClientCodegen();
|
||||
codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.JAVA8.value);
|
||||
codegen.processOpts();
|
||||
|
||||
final CodegenModel cm = codegen.fromModel("sample", schema);
|
||||
|
||||
final CodegenProperty property3 = cm.vars.get(2);
|
||||
Assert.assertEquals(property3.baseName, "createdAt");
|
||||
Assert.assertEquals(property3.datatype, "java.time.LocalDateTime");
|
||||
Assert.assertEquals(property3.name, "createdAt");
|
||||
Assert.assertEquals(property3.defaultValue, "null");
|
||||
Assert.assertEquals(property3.baseType, "java.time.LocalDateTime");
|
||||
Assert.assertFalse(property3.hasMore);
|
||||
Assert.assertFalse(property3.required);
|
||||
Assert.assertTrue(property3.isNotContainer);
|
||||
}
|
||||
|
||||
@Test(description = "convert a model with array property to default kotlin.Array")
|
||||
public void arrayPropertyTest() {
|
||||
final Schema model = getArrayTestSchema();
|
||||
|
||||
final DefaultCodegen codegen = new KotlinClientCodegen();
|
||||
final CodegenModel generated = codegen.fromModel("sample", model);
|
||||
|
||||
Assert.assertEquals(generated.name, "sample");
|
||||
Assert.assertEquals(generated.classname, "Sample");
|
||||
Assert.assertEquals(generated.description, "a sample model");
|
||||
Assert.assertEquals(generated.vars.size(), 2);
|
||||
|
||||
final CodegenProperty property = generated.vars.get(1);
|
||||
Assert.assertEquals(property.baseName, "examples");
|
||||
Assert.assertEquals(property.getter, "getExamples");
|
||||
Assert.assertEquals(property.setter, "setExamples");
|
||||
Assert.assertEquals(property.datatype, "kotlin.Array<kotlin.String>");
|
||||
Assert.assertEquals(property.name, "examples");
|
||||
Assert.assertEquals(property.defaultValue, "null");
|
||||
Assert.assertEquals(property.baseType, "kotlin.Array");
|
||||
Assert.assertEquals(property.containerType, "array");
|
||||
Assert.assertFalse(property.required);
|
||||
Assert.assertTrue(property.isContainer);
|
||||
}
|
||||
|
||||
@Test(description = "convert a model with a map property")
|
||||
public void mapPropertyTest() {
|
||||
final Schema schema = getMapSchema();
|
||||
final DefaultCodegen codegen = new KotlinClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel("sample", schema);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a sample model");
|
||||
Assert.assertEquals(cm.vars.size(), 1);
|
||||
|
||||
final CodegenProperty property1 = cm.vars.get(0);
|
||||
Assert.assertEquals(property1.baseName, "mapping");
|
||||
Assert.assertEquals(property1.datatype, "kotlin.collections.Map<kotlin.String, kotlin.String>");
|
||||
Assert.assertEquals(property1.name, "mapping");
|
||||
Assert.assertEquals(property1.baseType, "kotlin.collections.Map");
|
||||
Assert.assertEquals(property1.containerType, "map");
|
||||
Assert.assertFalse(property1.required);
|
||||
Assert.assertTrue(property1.isContainer);
|
||||
Assert.assertTrue(property1.isPrimitiveType);
|
||||
}
|
||||
|
||||
@Test(description = "convert a model with complex property")
|
||||
public void complexPropertyTest() {
|
||||
final Schema schema = getComplexSchema();
|
||||
final DefaultCodegen codegen = new KotlinClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel("sample", schema);
|
||||
|
||||
Assert.assertEquals(cm.name, "sample");
|
||||
Assert.assertEquals(cm.classname, "Sample");
|
||||
Assert.assertEquals(cm.description, "a sample model");
|
||||
Assert.assertEquals(cm.vars.size(), 1);
|
||||
|
||||
final CodegenProperty property1 = cm.vars.get(0);
|
||||
Assert.assertEquals(property1.baseName, "child");
|
||||
Assert.assertEquals(property1.datatype, "Child");
|
||||
Assert.assertEquals(property1.name, "child");
|
||||
Assert.assertEquals(property1.baseType, "Child");
|
||||
Assert.assertFalse(property1.required);
|
||||
Assert.assertTrue(property1.isNotContainer);
|
||||
}
|
||||
|
||||
@DataProvider(name = "modelNames")
|
||||
public static Object[][] modelNames() {
|
||||
return new Object[][]{
|
||||
{"TestNs.TestClass", new ModelNameTest("TestNs.TestClass", "TestNsTestClass")},
|
||||
{"$", new ModelNameTest("$", "Dollar")},
|
||||
{"for", new ModelNameTest("`for`", "For")},
|
||||
{"One<Two", new ModelNameTest("One<Two", "OneLessThanTwo")},
|
||||
{"this is a test", new ModelNameTest("this is a test", "ThisIsATest")}
|
||||
};
|
||||
}
|
||||
|
||||
@Test(dataProvider = "modelNames", description = "sanitize model names")
|
||||
public void sanitizeModelNames(final String name, final ModelNameTest testCase) {
|
||||
final Schema schema = getComplexSchema();
|
||||
final DefaultCodegen codegen = new KotlinClientCodegen();
|
||||
final CodegenModel cm = codegen.fromModel(name, schema);
|
||||
|
||||
Assert.assertEquals(cm.name, testCase.expectedName);
|
||||
Assert.assertEquals(cm.classname, testCase.expectedClassName);
|
||||
}
|
||||
|
||||
private static class ModelNameTest {
|
||||
private String expectedName;
|
||||
private String expectedClassName;
|
||||
|
||||
private ModelNameTest(String nameAndClass) {
|
||||
this.expectedName = nameAndClass;
|
||||
this.expectedClassName = nameAndClass;
|
||||
}
|
||||
|
||||
private ModelNameTest(String expectedName, String expectedClassName) {
|
||||
this.expectedName = expectedName;
|
||||
this.expectedClassName = expectedClassName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user