From dee0948e3e24a399d650c216e0408c8b4c6d5396 Mon Sep 17 00:00:00 2001 From: Ron Date: Mon, 15 Jun 2015 13:19:56 +0300 Subject: [PATCH 01/67] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cace22c92e9..f2c44ebf718 100644 --- a/README.md +++ b/README.md @@ -199,7 +199,7 @@ java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar generate \ Supported config options can be different per language. Running `config-help -l {lang}` will show available options. ``` -java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jarr config-help -l java +java -jar modules/swagger-codegen-cli/target/swagger-codegen-cli.jar config-help -l java ``` Output From f87bb12ebb3264097c81598e0bb1aec0fdc879a5 Mon Sep 17 00:00:00 2001 From: Martin Hardorf Date: Tue, 16 Jun 2015 10:44:05 +0200 Subject: [PATCH 02/67] Added support for TypeScript generation for AngularJS and Node.js --- .../TypeScriptAngularClientCodegen.java | 25 +++ .../TypeScriptNodeClientCodegen.java | 169 ++++++++++++++++++ .../services/io.swagger.codegen.CodegenConfig | 2 + .../TypeScript-Angular/api.d.mustache | 13 ++ .../resources/TypeScript-Angular/api.mustache | 68 +++++++ .../TypeScript-Angular/model.mustache | 30 ++++ .../resources/TypeScript-node/api.mustache | 73 ++++++++ .../resources/TypeScript-node/model.mustache | 24 +++ 8 files changed, 404 insertions(+) create mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/TypeScriptAngularClientCodegen.java create mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/TypeScriptNodeClientCodegen.java create mode 100644 modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.d.mustache create mode 100644 modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache create mode 100644 modules/swagger-codegen/src/main/resources/TypeScript-Angular/model.mustache create mode 100644 modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache create mode 100644 modules/swagger-codegen/src/main/resources/TypeScript-node/model.mustache diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/TypeScriptAngularClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/TypeScriptAngularClientCodegen.java new file mode 100644 index 00000000000..a31e15878cf --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/TypeScriptAngularClientCodegen.java @@ -0,0 +1,25 @@ +package io.swagger.codegen.languages; + +import java.io.File; + +import io.swagger.codegen.SupportingFile; + +public class TypeScriptAngularClientCodegen extends TypeScriptNodeClientCodegen { + + @Override + public String getName() { + return "typescript-angular"; + } + + public TypeScriptAngularClientCodegen() { + super(); + outputFolder = "generated-code/typescript-angular"; + modelTemplateFiles.put("model.mustache", ".ts"); + apiTemplateFiles.put("api.mustache", ".ts"); + templateDir = "TypeScript-Angular"; + apiPackage = "api"; + modelPackage = "api"; + + supportingFiles.add(new SupportingFile("api.d.mustache", apiPackage + File.separator, "api.d.ts")); + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/TypeScriptNodeClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/TypeScriptNodeClientCodegen.java new file mode 100644 index 00000000000..19b8514f8e3 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/TypeScriptNodeClientCodegen.java @@ -0,0 +1,169 @@ +package io.swagger.codegen.languages; + +import io.swagger.codegen.*; +import io.swagger.models.properties.*; + +import java.util.*; +import java.io.File; + +public class TypeScriptNodeClientCodegen extends DefaultCodegen implements CodegenConfig { + protected String invokerPackage = "io.swagger.client"; + protected String groupId = "io.swagger"; + protected String artifactId = "swagger-typescript-node-client"; + protected String artifactVersion = "1.0.0"; + protected String sourceFolder = "src/main/typescript"; + + @Override + public CodegenType getTag() { + return CodegenType.CLIENT; + } + + @Override + public String getName() { + return "typescript-node"; + } + + @Override + public String getHelp() { + return "Generates a TypeScript nodejs client library."; + } + + public TypeScriptNodeClientCodegen() { + super(); + outputFolder = "generated-code/typescript-node"; + modelTemplateFiles.put("model.mustache", ".ts"); + apiTemplateFiles.put("api.mustache", ".ts"); + templateDir = "TypeScript-node"; + apiPackage = "api"; + modelPackage = "model"; + + reservedWords = new HashSet(Arrays.asList("abstract", + "continue", "for", "new", "switch", "assert", "default", "if", + "package", "synchronized", "do", "goto", "private", + "this", "break", "double", "implements", "protected", "throw", + "byte", "else", "import", "public", "throws", "case", "enum", + "instanceof", "return", "transient", "catch", "extends", "int", + "short", "try", "char", "final", "interface", "static", "void", + "class", "finally", "const", "super", "while")); + + additionalProperties.put("invokerPackage", invokerPackage); + additionalProperties.put("groupId", groupId); + additionalProperties.put("artifactId", artifactId); + additionalProperties.put("artifactVersion", artifactVersion); + + languageSpecificPrimitives = new HashSet(Arrays.asList( + "String", + "boolean", + "Boolean", + "Double", + "Integer", + "Long", + "Float", + "Object")); + instantiationTypes.put("array", "Array"); + + typeMapping = new HashMap(); + typeMapping.put("Array", "Array"); + typeMapping.put("array", "Array"); + typeMapping.put("List", "Array"); + typeMapping.put("boolean", "boolean"); + typeMapping.put("string", "string"); + typeMapping.put("int", "number"); + typeMapping.put("float", "number"); + typeMapping.put("number", "number"); + typeMapping.put("long", "number"); + typeMapping.put("short", "number"); + typeMapping.put("char", "string"); + typeMapping.put("double", "number"); + typeMapping.put("object", "any"); + typeMapping.put("integer", "number"); + + } + + @Override + public String escapeReservedWord(String name) { + return "_" + name; + } + + @Override + public String apiFileFolder() { + return outputFolder + "/" + apiPackage().replace('.', File.separatorChar); + } + + public String modelFileFolder() { + return outputFolder + "/" + modelPackage().replace('.', File.separatorChar); + } + + @Override + public String toVarName(String name) { + // replace - with _ e.g. created-at => created_at + name = name.replaceAll("-", "_"); + + // if it's all uppper case, do nothing + if (name.matches("^[A-Z_]*$")) + return name; + + // camelize the variable name + // pet_id => PetId + name = camelize(name, true); + + // for reserved word or word starting with number, append _ + if (reservedWords.contains(name) || name.matches("^\\d.*")) + name = escapeReservedWord(name); + + return name; + } + + @Override + public String toParamName(String name) { + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toModelName(String name) { + // model name cannot use reserved keyword, e.g. return + if (reservedWords.contains(name)) + throw new RuntimeException(name + + " (reserved word) cannot be used as a model name"); + + // camelize the model name + // phone_number => PhoneNumber + return camelize(name); + } + + @Override + public String toModelFilename(String name) { + // should be the same as the model name + return toModelName(name); + } + + @Override + public String getTypeDeclaration(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + return getSwaggerType(p) + "<" + getTypeDeclaration(inner) + ">"; + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + + return getSwaggerType(p) + ""; + } + return super.getTypeDeclaration(p); + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + String type = null; + if (typeMapping.containsKey(swaggerType)) { + type = typeMapping.get(swaggerType); + if (languageSpecificPrimitives.contains(type)) + return type; + } else + type = swaggerType; + return type; + } +} diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index 8bbdbc8d140..2a037204976 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -21,4 +21,6 @@ io.swagger.codegen.languages.SwaggerGenerator io.swagger.codegen.languages.SwaggerYamlGenerator io.swagger.codegen.languages.SwiftGenerator io.swagger.codegen.languages.TizenClientCodegen +io.swagger.codegen.languages.TypeScriptAngularClientCodegen +io.swagger.codegen.languages.TypeScriptNodeClientCodegen io.swagger.codegen.languages.AkkaScalaClientCodegen diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.d.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.d.mustache new file mode 100644 index 00000000000..a8bf1c58267 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.d.mustache @@ -0,0 +1,13 @@ +{{#models}} +{{#model}} +/// +{{/model}} +{{/models}} + +{{#apiInfo}} +{{#apis}} +{{#operations}} +/// +{{/operations}} +{{/apis}} +{{/apiInfo}} diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache new file mode 100644 index 00000000000..3b53e816891 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache @@ -0,0 +1,68 @@ +/// + +/* tslint:disable:no-unused-variable member-ordering */ + +{{#operations}} +module {{package}} { + 'use strict'; + + {{#description}} + /** + * {{&description}} + */ + {{/description}} + export class {{classname}} { + private basePath = '{{basePath}}'; + + static $inject: string[] = ['$http']; + + constructor(private $http: ng.IHttpService, basePath?: string) { + if (basePath) { + this.basePath = basePath; + } + } + {{#operation}} + public {{nickname}} ({{#allParams}}{{paramName}}: {{{dataType}}}, {{/allParams}} extraHttpRequestParams?: any ) : ng.IHttpPromise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}{}{{/returnType}}> { + var path = this.basePath + '{{path}}'; + {{#pathParams}} + path = path.replace('{' + '{{paramName}}' + '}', String({{paramName}})); + {{/pathParams}} + var queryParameters: any = {}; + var headers: any = {}; + {{#requiredParamCount}} + // verify required params are set + if ({{/requiredParamCount}}{{#requiredParams}} !{{paramName}} {{#hasMore}}|| {{/hasMore}}{{/requiredParams}}{{#requiredParamCount}}) { + throw new Error('Missing required parameter: {{¶mName}}'); + } + {{/requiredParamCount}} + {{#queryParams}}if ({{paramName}} !== undefined) { + queryParameters['{{paramName}}'] = {{paramName}}; + }{{/queryParams}} + {{#headerParams}}headerParams['{{paramName}}'] = {{paramName}};{{/headerParams}} + var httpRequestParams: any = { + method: '{{httpMethod}}', + url: path, + json: true, + {{#bodyParam}}data: body, + {{/bodyParam}} + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + {{/operation}} + } + + angular.module('{{package}}_{{classname}}', ['$http']) + .service('{{classname}}', {{classname}}); +} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-Angular/model.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/model.mustache new file mode 100644 index 00000000000..bbda64b37da --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/model.mustache @@ -0,0 +1,30 @@ +/// + +module {{package}} { + 'use strict'; +{{#models}} +{{#model}} + {{#description}}/** + * {{{description}}} + */{{/description}} + export class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{ +{{#vars}} + {{#description}}/** + * {{{description}}} + */{{/description}} + {{name}}: {{#isEnum}}{{classname}}.{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}}; +{{/vars}} + } + +{{#hasEnums}} + export module {{classname}} { +{{#vars}} + {{#isEnum}}export enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} + {{.}} = '{{.}}',{{/values}}{{/allowableValues}} + }{{/isEnum}} +{{/vars}} + } +{{/hasEnums}} +{{/model}} +{{/models}} +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache new file mode 100644 index 00000000000..4b329799ad5 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache @@ -0,0 +1,73 @@ +/* tslint:disable:no-unused-variable */ + +{{#operations}} +{{#description}} + /** + * {{&description}} + */ +{{/description}} +export class {{classname}} { + private basePath = '{{basePath}}'; + + constructor(private url: string, private username: string, private password: string, basePath?: string) { + if (basePath) { + this.basePath = basePath; + } + } + + {{#operation}} + public {{nickname}} ({{#allParams}}{{paramName}}: {{{dataType}}}{{#hasMore}}, {{/hasMore}}{{/allParams}} ) : Promise<{ response: http.ClientResponse; {{#returnType}}body: {{{returnType}}}; {{/returnType}} }> { + var path = this.url + this.basePath + '{{path}}'; + + {{#pathParams}} + path = path.replace('{' + '{{paramName}}' + '}', String({{paramName}})); + {{/pathParams}} + + var queryParameters: any = {}; + var headers: any = {}; + + {{#requiredParamCount}} + // verify required params are set + if ({{/requiredParamCount}}{{#requiredParams}} !{{paramName}} {{#hasMore}}|| {{/hasMore}}{{/requiredParams}}{{#requiredParamCount}}) { + throw new Error('Missing required parameter: {{¶mName}}'); + } + {{/requiredParamCount}} + + {{#queryParams}}if ({{paramName}} !== undefined) { + queryParameters['{{paramName}}'] = {{paramName}}; + } + {{/queryParams}} + + {{#headerParams}}headerParams['{{paramName}}'] = {{paramName}}; + {{/headerParams}} + + var deferred = promise.defer<{ response: http.ClientResponse; {{#returnType}}body: {{{returnType}}}; {{/returnType}} }>(); + + request({ + method: '{{httpMethod}}', + qs: queryParameters, + uri: path, + json: true, + {{#bodyParam}}body: body, + {{/bodyParam}} + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + {{/operation}} +} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-node/model.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-node/model.mustache new file mode 100644 index 00000000000..f187ac3e40f --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/TypeScript-node/model.mustache @@ -0,0 +1,24 @@ +{{#models}} +{{#model}} +{{#description}}/** +* {{{description}}} +*/{{/description}} +export class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{ + {{#vars}}{{#description}}/** + * {{{description}}} + */ + {{/description}} + {{name}}: {{#isEnum}}{{classname}}.{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}};{{/vars}} +} + +{{#hasEnums}} +export module {{classname}} { +{{#vars}} + {{#isEnum}}export enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} + {{.}} = '{{.}}',{{/values}}{{/allowableValues}} + }{{/isEnum}} +{{/vars}} +} +{{/hasEnums}} +{{/model}} +{{/models}} From 5f1df9e093eaf7b584c98879b4e05dcf1ac8c58f Mon Sep 17 00:00:00 2001 From: Shane Oatman Date: Tue, 16 Jun 2015 12:12:17 -0700 Subject: [PATCH 03/67] Updates to csharp model template to support inheritance --- .../src/main/resources/csharp/model.mustache | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/csharp/model.mustache b/modules/swagger-codegen/src/main/resources/csharp/model.mustache index ce0e62de192..111c98993a2 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/model.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/model.mustache @@ -13,7 +13,7 @@ namespace {{package}} { /// {{description}} /// [DataContract] - public class {{classname}} { + public class {{classname}}{{#parent}} : {{{parent}}}{{/parent}} { {{#vars}} {{#description}}/* {{{description}}} */{{/description}} [DataMember(Name="{{baseName}}", EmitDefaultValue=false)] @@ -39,11 +39,11 @@ namespace {{package}} { /// Get the JSON string presentation of the object /// /// JSON string presentation of the object - public string ToJson() { + public {{#parent}} new {{/parent}}string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } } {{/model}} {{/models}} -} +} \ No newline at end of file From ba4b88ef86d512e8827e5cdd9c2ad433752e36b5 Mon Sep 17 00:00:00 2001 From: Martin Hardorf Date: Wed, 17 Jun 2015 12:22:15 +0200 Subject: [PATCH 04/67] Fixed TypeScript mustache --- .../TypeScript-Angular/model.mustache | 25 +++++++++++----- .../resources/TypeScript-node/model.mustache | 29 ++++++++++++------- 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-Angular/model.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/model.mustache index bbda64b37da..b425d14d5e4 100644 --- a/modules/swagger-codegen/src/main/resources/TypeScript-Angular/model.mustache +++ b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/model.mustache @@ -2,16 +2,22 @@ module {{package}} { 'use strict'; + {{#models}} {{#model}} - {{#description}}/** - * {{{description}}} - */{{/description}} +{{#description}} + /** + * {{{description}}} + */ +{{/description}} export class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{ {{#vars}} - {{#description}}/** - * {{{description}}} - */{{/description}} + +{{#description}} + /** + * {{{description}}} + */ +{{/description}} {{name}}: {{#isEnum}}{{classname}}.{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}}; {{/vars}} } @@ -19,9 +25,12 @@ module {{package}} { {{#hasEnums}} export module {{classname}} { {{#vars}} - {{#isEnum}}export enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} +{{#isEnum}} + + export enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} {{.}} = '{{.}}',{{/values}}{{/allowableValues}} - }{{/isEnum}} + } +{{/isEnum}} {{/vars}} } {{/hasEnums}} diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-node/model.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-node/model.mustache index f187ac3e40f..55c8997e1bc 100644 --- a/modules/swagger-codegen/src/main/resources/TypeScript-node/model.mustache +++ b/modules/swagger-codegen/src/main/resources/TypeScript-node/model.mustache @@ -1,22 +1,31 @@ {{#models}} {{#model}} -{{#description}}/** -* {{{description}}} -*/{{/description}} +{{#description}} +/** + * {{{description}}} + */ +{{/description}} export class {{classname}} {{#parent}}extends {{{parent}}} {{/parent}}{ - {{#vars}}{{#description}}/** - * {{{description}}} - */ - {{/description}} - {{name}}: {{#isEnum}}{{classname}}.{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}};{{/vars}} +{{#vars}} + +{{#description}} + /** + * {{{description}}} + */ +{{/description}} + {{name}}: {{#isEnum}}{{classname}}.{{{datatypeWithEnum}}}{{/isEnum}}{{^isEnum}}{{{datatype}}}{{/isEnum}}; +{{/vars}} } {{#hasEnums}} export module {{classname}} { {{#vars}} - {{#isEnum}}export enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} +{{#isEnum}} + + export enum {{datatypeWithEnum}} { {{#allowableValues}}{{#values}} {{.}} = '{{.}}',{{/values}}{{/allowableValues}} - }{{/isEnum}} + } +{{/isEnum}} {{/vars}} } {{/hasEnums}} From 9e8631b75f4a1fae6bd20106841092257b21a99d Mon Sep 17 00:00:00 2001 From: Martin Hardorf Date: Wed, 17 Jun 2015 17:56:37 +0200 Subject: [PATCH 05/67] Added shell scripts for sample generation of TypeScript --- bin/all-petstore.sh | 2 + bin/typescript-angular-petstore.sh | 31 ++ bin/typescript-node-petstore.sh | 31 ++ .../typescript-angular/api/Category.ts | 13 + .../petstore/typescript-angular/api/Order.ts | 32 ++ .../petstore/typescript-angular/api/Pet.ts | 32 ++ .../petstore/typescript-angular/api/PetApi.ts | 262 +++++++++++++ .../typescript-angular/api/StoreApi.ts | 141 +++++++ .../petstore/typescript-angular/api/Tag.ts | 13 + .../petstore/typescript-angular/api/User.ts | 28 ++ .../typescript-angular/api/UserApi.ts | 262 +++++++++++++ .../petstore/typescript-angular/api/api.d.ts | 9 + .../petstore/typescript-node/api/PetApi.ts | 358 ++++++++++++++++++ .../petstore/typescript-node/api/StoreApi.ts | 182 +++++++++ .../petstore/typescript-node/api/UserApi.ts | 357 +++++++++++++++++ .../typescript-node/model/Category.ts | 7 + .../petstore/typescript-node/model/Order.ts | 26 ++ .../petstore/typescript-node/model/Pet.ts | 26 ++ .../petstore/typescript-node/model/Tag.ts | 7 + .../petstore/typescript-node/model/User.ts | 22 ++ 20 files changed, 1841 insertions(+) create mode 100755 bin/typescript-angular-petstore.sh create mode 100755 bin/typescript-node-petstore.sh create mode 100644 samples/client/petstore/typescript-angular/api/Category.ts create mode 100644 samples/client/petstore/typescript-angular/api/Order.ts create mode 100644 samples/client/petstore/typescript-angular/api/Pet.ts create mode 100644 samples/client/petstore/typescript-angular/api/PetApi.ts create mode 100644 samples/client/petstore/typescript-angular/api/StoreApi.ts create mode 100644 samples/client/petstore/typescript-angular/api/Tag.ts create mode 100644 samples/client/petstore/typescript-angular/api/User.ts create mode 100644 samples/client/petstore/typescript-angular/api/UserApi.ts create mode 100644 samples/client/petstore/typescript-angular/api/api.d.ts create mode 100644 samples/client/petstore/typescript-node/api/PetApi.ts create mode 100644 samples/client/petstore/typescript-node/api/StoreApi.ts create mode 100644 samples/client/petstore/typescript-node/api/UserApi.ts create mode 100644 samples/client/petstore/typescript-node/model/Category.ts create mode 100644 samples/client/petstore/typescript-node/model/Order.ts create mode 100644 samples/client/petstore/typescript-node/model/Pet.ts create mode 100644 samples/client/petstore/typescript-node/model/Tag.ts create mode 100644 samples/client/petstore/typescript-node/model/User.ts diff --git a/bin/all-petstore.sh b/bin/all-petstore.sh index 8937200c77f..2f72165f1e5 100755 --- a/bin/all-petstore.sh +++ b/bin/all-petstore.sh @@ -34,3 +34,5 @@ cd $APP_DIR ./bin/scala-petstore.sh ./bin/spring-mvc-petstore-server.sh ./bin/tizen-petstore.sh +./bin/typescript-angular-petstore.sh +./bin/typescript-node-petstore.sh diff --git a/bin/typescript-angular-petstore.sh b/bin/typescript-angular-petstore.sh new file mode 100755 index 00000000000..60c10790c90 --- /dev/null +++ b/bin/typescript-angular-petstore.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l typescript-angular -o samples/client/petstore/typescript-angular" + +java $JAVA_OPTS -jar $executable $ags diff --git a/bin/typescript-node-petstore.sh b/bin/typescript-node-petstore.sh new file mode 100755 index 00000000000..53c5a6f8d82 --- /dev/null +++ b/bin/typescript-node-petstore.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l typescript-node -o samples/client/petstore/typescript-node" + +java $JAVA_OPTS -jar $executable $ags diff --git a/samples/client/petstore/typescript-angular/api/Category.ts b/samples/client/petstore/typescript-angular/api/Category.ts new file mode 100644 index 00000000000..e4a3caa208e --- /dev/null +++ b/samples/client/petstore/typescript-angular/api/Category.ts @@ -0,0 +1,13 @@ +/// + +module api { + 'use strict'; + + export class Category { + + id: number; + + name: string; + } + +} \ No newline at end of file diff --git a/samples/client/petstore/typescript-angular/api/Order.ts b/samples/client/petstore/typescript-angular/api/Order.ts new file mode 100644 index 00000000000..3f37c608758 --- /dev/null +++ b/samples/client/petstore/typescript-angular/api/Order.ts @@ -0,0 +1,32 @@ +/// + +module api { + 'use strict'; + + export class Order { + + id: number; + + petId: number; + + quantity: number; + + shipDate: DateTime; + + /** + * Order Status + */ + status: Order.StatusEnum; + + complete: boolean; + } + + export module Order { + + export enum StatusEnum { + placed = 'placed', + approved = 'approved', + delivered = 'delivered', + } + } +} \ No newline at end of file diff --git a/samples/client/petstore/typescript-angular/api/Pet.ts b/samples/client/petstore/typescript-angular/api/Pet.ts new file mode 100644 index 00000000000..c34be9c3dbc --- /dev/null +++ b/samples/client/petstore/typescript-angular/api/Pet.ts @@ -0,0 +1,32 @@ +/// + +module api { + 'use strict'; + + export class Pet { + + id: number; + + category: Category; + + name: string; + + photoUrls: Array; + + tags: Array; + + /** + * pet status in the store + */ + status: Pet.StatusEnum; + } + + export module Pet { + + export enum StatusEnum { + available = 'available', + pending = 'pending', + sold = 'sold', + } + } +} \ No newline at end of file diff --git a/samples/client/petstore/typescript-angular/api/PetApi.ts b/samples/client/petstore/typescript-angular/api/PetApi.ts new file mode 100644 index 00000000000..2c5f2a25b6d --- /dev/null +++ b/samples/client/petstore/typescript-angular/api/PetApi.ts @@ -0,0 +1,262 @@ +/// + +/* tslint:disable:no-unused-variable member-ordering */ + +module api { + 'use strict'; + + + export class PetApi { + private basePath = 'http://petstore.swagger.io/v2'; + + static $inject: string[] = ['$http']; + + constructor(private $http: ng.IHttpService, basePath?: string) { + if (basePath) { + this.basePath = basePath; + } + } + + public updatePet (body: Pet, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/pet'; + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'PUT', + url: path, + json: true, + data: body, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public addPet (body: Pet, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/pet'; + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'POST', + url: path, + json: true, + data: body, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public findPetsByStatus (status: Array, extraHttpRequestParams?: any ) : ng.IHttpPromise> { + var path = this.basePath + '/pet/findByStatus'; + + var queryParameters: any = {}; + var headers: any = {}; + + if (status !== undefined) { + queryParameters['status'] = status; + } + + var httpRequestParams: any = { + method: 'GET', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public findPetsByTags (tags: Array, extraHttpRequestParams?: any ) : ng.IHttpPromise> { + var path = this.basePath + '/pet/findByTags'; + + var queryParameters: any = {}; + var headers: any = {}; + + if (tags !== undefined) { + queryParameters['tags'] = tags; + } + + var httpRequestParams: any = { + method: 'GET', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public getPetById (petId: number, extraHttpRequestParams?: any ) : ng.IHttpPromise { + var path = this.basePath + '/pet/{petId}'; + + path = path.replace('{' + 'petId' + '}', String(petId)); + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'GET', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public updatePetWithForm (petId: string, name: string, status: string, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/pet/{petId}'; + + path = path.replace('{' + 'petId' + '}', String(petId)); + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'POST', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public deletePet (apiKey: string, petId: number, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/pet/{petId}'; + + path = path.replace('{' + 'petId' + '}', String(petId)); + + var queryParameters: any = {}; + var headers: any = {}; + + + headerParams['apiKey'] = apiKey; + var httpRequestParams: any = { + method: 'DELETE', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public uploadFile (petId: number, additionalMetadata: string, file: file, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/pet/{petId}/uploadImage'; + + path = path.replace('{' + 'petId' + '}', String(petId)); + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'POST', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + } + + angular.module('api_PetApi', ['$http']) + .service('PetApi', PetApi); +} diff --git a/samples/client/petstore/typescript-angular/api/StoreApi.ts b/samples/client/petstore/typescript-angular/api/StoreApi.ts new file mode 100644 index 00000000000..e4c9e48e0e9 --- /dev/null +++ b/samples/client/petstore/typescript-angular/api/StoreApi.ts @@ -0,0 +1,141 @@ +/// + +/* tslint:disable:no-unused-variable member-ordering */ + +module api { + 'use strict'; + + + export class StoreApi { + private basePath = 'http://petstore.swagger.io/v2'; + + static $inject: string[] = ['$http']; + + constructor(private $http: ng.IHttpService, basePath?: string) { + if (basePath) { + this.basePath = basePath; + } + } + + public getInventory ( extraHttpRequestParams?: any ) : ng.IHttpPromise> { + var path = this.basePath + '/store/inventory'; + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'GET', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public placeOrder (body: Order, extraHttpRequestParams?: any ) : ng.IHttpPromise { + var path = this.basePath + '/store/order'; + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'POST', + url: path, + json: true, + data: body, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public getOrderById (orderId: string, extraHttpRequestParams?: any ) : ng.IHttpPromise { + var path = this.basePath + '/store/order/{orderId}'; + + path = path.replace('{' + 'orderId' + '}', String(orderId)); + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'GET', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public deleteOrder (orderId: string, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/store/order/{orderId}'; + + path = path.replace('{' + 'orderId' + '}', String(orderId)); + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'DELETE', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + } + + angular.module('api_StoreApi', ['$http']) + .service('StoreApi', StoreApi); +} diff --git a/samples/client/petstore/typescript-angular/api/Tag.ts b/samples/client/petstore/typescript-angular/api/Tag.ts new file mode 100644 index 00000000000..33f0ffaa1e2 --- /dev/null +++ b/samples/client/petstore/typescript-angular/api/Tag.ts @@ -0,0 +1,13 @@ +/// + +module api { + 'use strict'; + + export class Tag { + + id: number; + + name: string; + } + +} \ No newline at end of file diff --git a/samples/client/petstore/typescript-angular/api/User.ts b/samples/client/petstore/typescript-angular/api/User.ts new file mode 100644 index 00000000000..57385044943 --- /dev/null +++ b/samples/client/petstore/typescript-angular/api/User.ts @@ -0,0 +1,28 @@ +/// + +module api { + 'use strict'; + + export class User { + + id: number; + + username: string; + + firstName: string; + + lastName: string; + + email: string; + + password: string; + + phone: string; + + /** + * User Status + */ + userStatus: number; + } + +} \ No newline at end of file diff --git a/samples/client/petstore/typescript-angular/api/UserApi.ts b/samples/client/petstore/typescript-angular/api/UserApi.ts new file mode 100644 index 00000000000..dfbe9032dba --- /dev/null +++ b/samples/client/petstore/typescript-angular/api/UserApi.ts @@ -0,0 +1,262 @@ +/// + +/* tslint:disable:no-unused-variable member-ordering */ + +module api { + 'use strict'; + + + export class UserApi { + private basePath = 'http://petstore.swagger.io/v2'; + + static $inject: string[] = ['$http']; + + constructor(private $http: ng.IHttpService, basePath?: string) { + if (basePath) { + this.basePath = basePath; + } + } + + public createUser (body: User, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/user'; + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'POST', + url: path, + json: true, + data: body, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public createUsersWithArrayInput (body: Array, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/user/createWithArray'; + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'POST', + url: path, + json: true, + data: body, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public createUsersWithListInput (body: Array, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/user/createWithList'; + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'POST', + url: path, + json: true, + data: body, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public loginUser (username: string, password: string, extraHttpRequestParams?: any ) : ng.IHttpPromise { + var path = this.basePath + '/user/login'; + + var queryParameters: any = {}; + var headers: any = {}; + + if (username !== undefined) { + queryParameters['username'] = username; + }if (password !== undefined) { + queryParameters['password'] = password; + } + + var httpRequestParams: any = { + method: 'GET', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public logoutUser ( extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/user/logout'; + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'GET', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public getUserByName (username: string, extraHttpRequestParams?: any ) : ng.IHttpPromise { + var path = this.basePath + '/user/{username}'; + + path = path.replace('{' + 'username' + '}', String(username)); + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'GET', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public updateUser (username: string, body: User, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/user/{username}'; + + path = path.replace('{' + 'username' + '}', String(username)); + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'PUT', + url: path, + json: true, + data: body, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + public deleteUser (username: string, extraHttpRequestParams?: any ) : ng.IHttpPromise<{}> { + var path = this.basePath + '/user/{username}'; + + path = path.replace('{' + 'username' + '}', String(username)); + + var queryParameters: any = {}; + var headers: any = {}; + + + + var httpRequestParams: any = { + method: 'DELETE', + url: path, + json: true, + + params: queryParameters, + headers: headers + }; + + if (extraHttpRequestParams) { + for (var k in extraHttpRequestParams){ + if (extraHttpRequestParams.hasOwnProperty(k)) { + httpRequestParams[k] = extraHttpRequestParams[k]; + } + } + } + + return this.$http(httpRequestParams); + } + + } + + angular.module('api_UserApi', ['$http']) + .service('UserApi', UserApi); +} diff --git a/samples/client/petstore/typescript-angular/api/api.d.ts b/samples/client/petstore/typescript-angular/api/api.d.ts new file mode 100644 index 00000000000..19c60623dc9 --- /dev/null +++ b/samples/client/petstore/typescript-angular/api/api.d.ts @@ -0,0 +1,9 @@ +/// +/// +/// +/// +/// + +/// +/// +/// diff --git a/samples/client/petstore/typescript-node/api/PetApi.ts b/samples/client/petstore/typescript-node/api/PetApi.ts new file mode 100644 index 00000000000..c948f8036e6 --- /dev/null +++ b/samples/client/petstore/typescript-node/api/PetApi.ts @@ -0,0 +1,358 @@ +/* tslint:disable:no-unused-variable */ + +export class PetApi { + private basePath = 'http://petstore.swagger.io/v2'; + + constructor(private url: string, private username: string, private password: string, basePath?: string) { + if (basePath) { + this.basePath = basePath; + } + } + + + public updatePet (body: Pet ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/pet'; + + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'PUT', + qs: queryParameters, + uri: path, + json: true, + body: body, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public addPet (body: Pet ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/pet'; + + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'POST', + qs: queryParameters, + uri: path, + json: true, + body: body, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public findPetsByStatus (status: Array ) : Promise<{ response: http.ClientResponse; body: Array; }> { + var path = this.url + this.basePath + '/pet/findByStatus'; + + + + var queryParameters: any = {}; + var headers: any = {}; + + + + if (status !== undefined) { + queryParameters['status'] = status; + } + + + + + var deferred = promise.defer<{ response: http.ClientResponse; body: Array; }>(); + + request({ + method: 'GET', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public findPetsByTags (tags: Array ) : Promise<{ response: http.ClientResponse; body: Array; }> { + var path = this.url + this.basePath + '/pet/findByTags'; + + + + var queryParameters: any = {}; + var headers: any = {}; + + + + if (tags !== undefined) { + queryParameters['tags'] = tags; + } + + + + + var deferred = promise.defer<{ response: http.ClientResponse; body: Array; }>(); + + request({ + method: 'GET', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public getPetById (petId: number ) : Promise<{ response: http.ClientResponse; body: Pet; }> { + var path = this.url + this.basePath + '/pet/{petId}'; + + + path = path.replace('{' + 'petId' + '}', String(petId)); + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; body: Pet; }>(); + + request({ + method: 'GET', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public updatePetWithForm (petId: string, name: string, status: string ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/pet/{petId}'; + + + path = path.replace('{' + 'petId' + '}', String(petId)); + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'POST', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public deletePet (apiKey: string, petId: number ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/pet/{petId}'; + + + path = path.replace('{' + 'petId' + '}', String(petId)); + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + headerParams['apiKey'] = apiKey; + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'DELETE', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public uploadFile (petId: number, additionalMetadata: string, file: file ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/pet/{petId}/uploadImage'; + + + path = path.replace('{' + 'petId' + '}', String(petId)); + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'POST', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + +} diff --git a/samples/client/petstore/typescript-node/api/StoreApi.ts b/samples/client/petstore/typescript-node/api/StoreApi.ts new file mode 100644 index 00000000000..1c2c6623523 --- /dev/null +++ b/samples/client/petstore/typescript-node/api/StoreApi.ts @@ -0,0 +1,182 @@ +/* tslint:disable:no-unused-variable */ + +export class StoreApi { + private basePath = 'http://petstore.swagger.io/v2'; + + constructor(private url: string, private username: string, private password: string, basePath?: string) { + if (basePath) { + this.basePath = basePath; + } + } + + + public getInventory ( ) : Promise<{ response: http.ClientResponse; body: map; }> { + var path = this.url + this.basePath + '/store/inventory'; + + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; body: map; }>(); + + request({ + method: 'GET', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public placeOrder (body: Order ) : Promise<{ response: http.ClientResponse; body: Order; }> { + var path = this.url + this.basePath + '/store/order'; + + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; body: Order; }>(); + + request({ + method: 'POST', + qs: queryParameters, + uri: path, + json: true, + body: body, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public getOrderById (orderId: string ) : Promise<{ response: http.ClientResponse; body: Order; }> { + var path = this.url + this.basePath + '/store/order/{orderId}'; + + + path = path.replace('{' + 'orderId' + '}', String(orderId)); + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; body: Order; }>(); + + request({ + method: 'GET', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public deleteOrder (orderId: string ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/store/order/{orderId}'; + + + path = path.replace('{' + 'orderId' + '}', String(orderId)); + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'DELETE', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + +} diff --git a/samples/client/petstore/typescript-node/api/UserApi.ts b/samples/client/petstore/typescript-node/api/UserApi.ts new file mode 100644 index 00000000000..fa4365f8edc --- /dev/null +++ b/samples/client/petstore/typescript-node/api/UserApi.ts @@ -0,0 +1,357 @@ +/* tslint:disable:no-unused-variable */ + +export class UserApi { + private basePath = 'http://petstore.swagger.io/v2'; + + constructor(private url: string, private username: string, private password: string, basePath?: string) { + if (basePath) { + this.basePath = basePath; + } + } + + + public createUser (body: User ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/user'; + + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'POST', + qs: queryParameters, + uri: path, + json: true, + body: body, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public createUsersWithArrayInput (body: Array ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/user/createWithArray'; + + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'POST', + qs: queryParameters, + uri: path, + json: true, + body: body, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public createUsersWithListInput (body: Array ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/user/createWithList'; + + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'POST', + qs: queryParameters, + uri: path, + json: true, + body: body, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public loginUser (username: string, password: string ) : Promise<{ response: http.ClientResponse; body: string; }> { + var path = this.url + this.basePath + '/user/login'; + + + + var queryParameters: any = {}; + var headers: any = {}; + + + + if (username !== undefined) { + queryParameters['username'] = username; + } + if (password !== undefined) { + queryParameters['password'] = password; + } + + + + + var deferred = promise.defer<{ response: http.ClientResponse; body: string; }>(); + + request({ + method: 'GET', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public logoutUser ( ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/user/logout'; + + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'GET', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public getUserByName (username: string ) : Promise<{ response: http.ClientResponse; body: User; }> { + var path = this.url + this.basePath + '/user/{username}'; + + + path = path.replace('{' + 'username' + '}', String(username)); + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; body: User; }>(); + + request({ + method: 'GET', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public updateUser (username: string, body: User ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/user/{username}'; + + + path = path.replace('{' + 'username' + '}', String(username)); + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'PUT', + qs: queryParameters, + uri: path, + json: true, + body: body, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + + public deleteUser (username: string ) : Promise<{ response: http.ClientResponse; }> { + var path = this.url + this.basePath + '/user/{username}'; + + + path = path.replace('{' + 'username' + '}', String(username)); + + + var queryParameters: any = {}; + var headers: any = {}; + + + + + + + + var deferred = promise.defer<{ response: http.ClientResponse; }>(); + + request({ + method: 'DELETE', + qs: queryParameters, + uri: path, + json: true, + + auth: { + username: this.username, password: this.password + } + }, (error, response, body) => { + if (error) { + deferred.reject(error); + } else { + if (response.statusCode >= 200 && response.statusCode <= 299) { + deferred.resolve({ response: response, body: body }); + } else { + deferred.reject({ response: response, body: body }); + } + } + }); + + return deferred.promise; + } + + +} diff --git a/samples/client/petstore/typescript-node/model/Category.ts b/samples/client/petstore/typescript-node/model/Category.ts new file mode 100644 index 00000000000..fc4b2874e93 --- /dev/null +++ b/samples/client/petstore/typescript-node/model/Category.ts @@ -0,0 +1,7 @@ +export class Category { + + id: number; + + name: string; +} + diff --git a/samples/client/petstore/typescript-node/model/Order.ts b/samples/client/petstore/typescript-node/model/Order.ts new file mode 100644 index 00000000000..b46ad4570a0 --- /dev/null +++ b/samples/client/petstore/typescript-node/model/Order.ts @@ -0,0 +1,26 @@ +export class Order { + + id: number; + + petId: number; + + quantity: number; + + shipDate: DateTime; + + /** + * Order Status + */ + status: Order.StatusEnum; + + complete: boolean; +} + +export module Order { + + export enum StatusEnum { + placed = 'placed', + approved = 'approved', + delivered = 'delivered', + } +} diff --git a/samples/client/petstore/typescript-node/model/Pet.ts b/samples/client/petstore/typescript-node/model/Pet.ts new file mode 100644 index 00000000000..4a3faa129ed --- /dev/null +++ b/samples/client/petstore/typescript-node/model/Pet.ts @@ -0,0 +1,26 @@ +export class Pet { + + id: number; + + category: Category; + + name: string; + + photoUrls: Array; + + tags: Array; + + /** + * pet status in the store + */ + status: Pet.StatusEnum; +} + +export module Pet { + + export enum StatusEnum { + available = 'available', + pending = 'pending', + sold = 'sold', + } +} diff --git a/samples/client/petstore/typescript-node/model/Tag.ts b/samples/client/petstore/typescript-node/model/Tag.ts new file mode 100644 index 00000000000..6ae0d4ef576 --- /dev/null +++ b/samples/client/petstore/typescript-node/model/Tag.ts @@ -0,0 +1,7 @@ +export class Tag { + + id: number; + + name: string; +} + diff --git a/samples/client/petstore/typescript-node/model/User.ts b/samples/client/petstore/typescript-node/model/User.ts new file mode 100644 index 00000000000..fee31563d13 --- /dev/null +++ b/samples/client/petstore/typescript-node/model/User.ts @@ -0,0 +1,22 @@ +export class User { + + id: number; + + username: string; + + firstName: string; + + lastName: string; + + email: string; + + password: string; + + phone: string; + + /** + * User Status + */ + userStatus: number; +} + From e7d4a438ddea8a9c5ba43c2526c4859a7622b013 Mon Sep 17 00:00:00 2001 From: Martin Hardorf Date: Wed, 17 Jun 2015 17:58:52 +0200 Subject: [PATCH 06/67] Added tests for TypeScript Angular and Node.js --- .../TypeScriptAngularModelTest.scala | 170 ++++++++++++++++++ .../TypeScriptNodeModelTest.scala | 170 ++++++++++++++++++ 2 files changed, 340 insertions(+) create mode 100644 modules/swagger-codegen/src/test/scala/typescriptangular/TypeScriptAngularModelTest.scala create mode 100644 modules/swagger-codegen/src/test/scala/typescriptnode/TypeScriptNodeModelTest.scala diff --git a/modules/swagger-codegen/src/test/scala/typescriptangular/TypeScriptAngularModelTest.scala b/modules/swagger-codegen/src/test/scala/typescriptangular/TypeScriptAngularModelTest.scala new file mode 100644 index 00000000000..5e28e3e8dc7 --- /dev/null +++ b/modules/swagger-codegen/src/test/scala/typescriptangular/TypeScriptAngularModelTest.scala @@ -0,0 +1,170 @@ +package typescriptangular + +import io.swagger.codegen.languages.TypeScriptAngularClientCodegen +import io.swagger.models._ +import io.swagger.models.properties._ +import org.junit.runner.RunWith +import org.scalatest.{FlatSpec, Matchers} +import org.scalatest.junit.JUnitRunner + +import scala.collection.JavaConverters._ + +@RunWith(classOf[JUnitRunner]) +class TypeScriptAngularModelTest extends FlatSpec with Matchers { + + it should "convert a simple TypeScript Angular model" in { + val model = new ModelImpl() + .description("a sample model") + .property("id", new LongProperty()) + .property("name", new StringProperty()) + .property("createdAt", new DateTimeProperty()) + .required("id") + .required("name") + + val codegen = new TypeScriptAngularClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("a sample model") + cm.vars.size should be(3) + + val vars = cm.vars + vars.get(0).baseName should be("id") + vars.get(0).datatype should be("number") + vars.get(0).name should be("id") + vars.get(0).defaultValue should be("null") + vars.get(0).baseType should be("number") + vars.get(0).hasMore should equal(true) + vars.get(0).required should equal(true) + vars.get(0).isNotContainer should equal(true) + + vars.get(1).baseName should be("name") + vars.get(1).datatype should be("string") + vars.get(1).name should be("name") + vars.get(1).defaultValue should be("null") + vars.get(1).baseType should be("string") + vars.get(1).hasMore should equal(true) + vars.get(1).required should equal(true) + vars.get(1).isNotContainer should equal(true) + + vars.get(2).baseName should be("createdAt") + vars.get(2).complexType should be("DateTime") + vars.get(2).datatype should be("DateTime") + vars.get(2).name should be("createdAt") + vars.get(2).defaultValue should be("null") + vars.get(2).hasMore should equal(null) + vars.get(2).required should equal(null) + vars.get(2).isNotContainer should equal(true) + } + + it should "convert a model with list property" in { + val model = new ModelImpl() + .description("a sample model") + .property("id", new LongProperty()) + .property("urls", new ArrayProperty() + .items(new StringProperty())) + .required("id") + + val codegen = new TypeScriptAngularClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("a sample model") + cm.vars.size should be(2) + + val vars = cm.vars + vars.get(0).baseName should be("id") + vars.get(0).datatype should be("number") + vars.get(0).name should be("id") + vars.get(0).defaultValue should be("null") + vars.get(0).baseType should be("number") + vars.get(0).hasMore should equal(true) + vars.get(0).required should equal(true) + vars.get(0).isNotContainer should equal(true) + + vars.get(1).baseName should be("urls") + vars.get(1).datatype should be("Array") + vars.get(1).name should be("urls") + vars.get(1).baseType should be("Array") + vars.get(1).hasMore should be(null) + vars.get(1).required should equal(null) + vars.get(1).isContainer should equal(true) + } + + it should "convert a model with complex property" in { + val model = new ModelImpl() + .description("a sample model") + .property("children", new RefProperty("#/definitions/Children")) + + val codegen = new TypeScriptAngularClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("a sample model") + cm.vars.size should be(1) + + val vars = cm.vars + vars.get(0).baseName should be("children") + vars.get(0).datatype should be("Children") + vars.get(0).name should be("children") + vars.get(0).baseType should be("Children") + vars.get(0).required should equal(null) + vars.get(0).isNotContainer should equal(true) + } + + it should "convert a model with complex list property" in { + val model = new ModelImpl() + .description("a sample model") + .property("children", new ArrayProperty() + .items(new RefProperty("#/definitions/Children"))) + + val codegen = new TypeScriptAngularClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("a sample model") + cm.vars.size should be(1) + + val vars = cm.vars + vars.get(0).baseName should be("children") + vars.get(0).complexType should be("Children") + vars.get(0).datatype should be("Array") + vars.get(0).name should be("children") + vars.get(0).baseType should be("Array") + vars.get(0).required should equal(null) + vars.get(0).isContainer should equal(true) + } + + it should "convert an array model" in { + val model = new ArrayModel() + .description("an array model") + .items(new RefProperty("#/definitions/Children")) + val codegen = new TypeScriptAngularClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("an array model") + cm.vars.size should be(0) + } + + it should "convert an map model" in { + val model = new ModelImpl() + .description("an map model") + .additionalProperties(new RefProperty("#/definitions/Children")) + + val codegen = new TypeScriptAngularClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("an map model") + cm.vars.size should be(0) + cm.imports.size should be(1) + (cm.imports.asScala.toSet & Set("Children")).size should be(1) + } +} diff --git a/modules/swagger-codegen/src/test/scala/typescriptnode/TypeScriptNodeModelTest.scala b/modules/swagger-codegen/src/test/scala/typescriptnode/TypeScriptNodeModelTest.scala new file mode 100644 index 00000000000..0b91d717bf6 --- /dev/null +++ b/modules/swagger-codegen/src/test/scala/typescriptnode/TypeScriptNodeModelTest.scala @@ -0,0 +1,170 @@ +package typescriptnode + +import io.swagger.codegen.languages.TypeScriptNodeClientCodegen +import io.swagger.models._ +import io.swagger.models.properties._ +import org.junit.runner.RunWith +import org.scalatest.{FlatSpec, Matchers} +import org.scalatest.junit.JUnitRunner + +import scala.collection.JavaConverters._ + +@RunWith(classOf[JUnitRunner]) +class TypeScriptNodeModelTest extends FlatSpec with Matchers { + + it should "convert a simple TypeScript Node model" in { + val model = new ModelImpl() + .description("a sample model") + .property("id", new LongProperty()) + .property("name", new StringProperty()) + .property("createdAt", new DateTimeProperty()) + .required("id") + .required("name") + + val codegen = new TypeScriptNodeClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("a sample model") + cm.vars.size should be(3) + + val vars = cm.vars + vars.get(0).baseName should be("id") + vars.get(0).datatype should be("number") + vars.get(0).name should be("id") + vars.get(0).defaultValue should be("null") + vars.get(0).baseType should be("number") + vars.get(0).hasMore should equal(true) + vars.get(0).required should equal(true) + vars.get(0).isNotContainer should equal(true) + + vars.get(1).baseName should be("name") + vars.get(1).datatype should be("string") + vars.get(1).name should be("name") + vars.get(1).defaultValue should be("null") + vars.get(1).baseType should be("string") + vars.get(1).hasMore should equal(true) + vars.get(1).required should equal(true) + vars.get(1).isNotContainer should equal(true) + + vars.get(2).baseName should be("createdAt") + vars.get(2).complexType should be("DateTime") + vars.get(2).datatype should be("DateTime") + vars.get(2).name should be("createdAt") + vars.get(2).defaultValue should be("null") + vars.get(2).hasMore should equal(null) + vars.get(2).required should equal(null) + vars.get(2).isNotContainer should equal(true) + } + + it should "convert a model with list property" in { + val model = new ModelImpl() + .description("a sample model") + .property("id", new LongProperty()) + .property("urls", new ArrayProperty() + .items(new StringProperty())) + .required("id") + + val codegen = new TypeScriptNodeClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("a sample model") + cm.vars.size should be(2) + + val vars = cm.vars + vars.get(0).baseName should be("id") + vars.get(0).datatype should be("number") + vars.get(0).name should be("id") + vars.get(0).defaultValue should be("null") + vars.get(0).baseType should be("number") + vars.get(0).hasMore should equal(true) + vars.get(0).required should equal(true) + vars.get(0).isNotContainer should equal(true) + + vars.get(1).baseName should be("urls") + vars.get(1).datatype should be("Array") + vars.get(1).name should be("urls") + vars.get(1).baseType should be("Array") + vars.get(1).hasMore should be(null) + vars.get(1).required should equal(null) + vars.get(1).isContainer should equal(true) + } + + it should "convert a model with complex property" in { + val model = new ModelImpl() + .description("a sample model") + .property("children", new RefProperty("#/definitions/Children")) + + val codegen = new TypeScriptNodeClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("a sample model") + cm.vars.size should be(1) + + val vars = cm.vars + vars.get(0).baseName should be("children") + vars.get(0).datatype should be("Children") + vars.get(0).name should be("children") + vars.get(0).baseType should be("Children") + vars.get(0).required should equal(null) + vars.get(0).isNotContainer should equal(true) + } + + it should "convert a model with complex list property" in { + val model = new ModelImpl() + .description("a sample model") + .property("children", new ArrayProperty() + .items(new RefProperty("#/definitions/Children"))) + + val codegen = new TypeScriptNodeClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("a sample model") + cm.vars.size should be(1) + + val vars = cm.vars + vars.get(0).baseName should be("children") + vars.get(0).complexType should be("Children") + vars.get(0).datatype should be("Array") + vars.get(0).name should be("children") + vars.get(0).baseType should be("Array") + vars.get(0).required should equal(null) + vars.get(0).isContainer should equal(true) + } + + it should "convert an array model" in { + val model = new ArrayModel() + .description("an array model") + .items(new RefProperty("#/definitions/Children")) + val codegen = new TypeScriptNodeClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("an array model") + cm.vars.size should be(0) + } + + it should "convert an map model" in { + val model = new ModelImpl() + .description("an map model") + .additionalProperties(new RefProperty("#/definitions/Children")) + + val codegen = new TypeScriptNodeClientCodegen() + val cm = codegen.fromModel("sample", model) + + cm.name should be("sample") + cm.classname should be("Sample") + cm.description should be("an map model") + cm.vars.size should be(0) + cm.imports.size should be(1) + (cm.imports.asScala.toSet & Set("Children")).size should be(1) + } +} From a32335dfbcb09bce83aeb4b214b2159e8e8724de Mon Sep 17 00:00:00 2001 From: geekerzp Date: Fri, 12 Jun 2015 17:51:05 +0800 Subject: [PATCH 07/67] Enable cli config options for python generator --- .../languages/PythonClientCodegen.java | 79 ++++++++++++++---- .../src/main/resources/python/setup.mustache | 7 +- .../Makefile | 0 .../README.md | 0 .../dev-requirements.txt | 0 .../pom.xml | 0 .../setup.cfg | 0 .../setup.py | 7 +- .../swagger_client}/__init__.py | 0 .../swagger_client}/api_client.py | 0 .../swagger_client}/apis/__init__.py | 0 .../swagger_client}/apis/pet_api.py | 0 .../swagger_client}/apis/store_api.py | 0 .../swagger_client}/apis/user_api.py | 0 .../swagger_client}/configuration.py | 0 .../swagger_client}/models/__init__.py | 0 .../swagger_client}/models/category.py | 0 .../swagger_client}/models/order.py | 0 .../swagger_client}/models/pet.py | 0 .../swagger_client}/models/tag.py | 0 .../swagger_client}/models/user.py | 0 .../swagger_client}/rest.py | 0 .../testfiles/foo.png | Bin .../tests/__init__.py | 0 .../tests/test_api_client.py | 20 ++--- .../tests/test_api_exception.py | 16 ++-- .../tests/test_pet_api.py | 30 +++---- .../tox.ini | 0 28 files changed, 105 insertions(+), 54 deletions(-) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/Makefile (100%) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/README.md (100%) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/dev-requirements.txt (100%) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/pom.xml (100%) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/setup.cfg (100%) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/setup.py (92%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/__init__.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/api_client.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/apis/__init__.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/apis/pet_api.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/apis/store_api.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/apis/user_api.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/configuration.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/models/__init__.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/models/category.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/models/order.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/models/pet.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/models/tag.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/models/user.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python/SwaggerPetstore => swagger_client_python/swagger_client}/rest.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/testfiles/foo.png (100%) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/tests/__init__.py (100%) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/tests/test_api_client.py (85%) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/tests/test_api_exception.py (85%) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/tests/test_pet_api.py (84%) rename samples/client/petstore/python/{SwaggerPetstore-python => swagger_client_python}/tox.ini (100%) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java index a14fa71f425..e5a3b0810b2 100755 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java @@ -1,5 +1,6 @@ package io.swagger.codegen.languages; +import io.swagger.codegen.CliOption; import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenType; import io.swagger.codegen.DefaultCodegen; @@ -13,25 +14,19 @@ import java.util.Arrays; import java.util.HashSet; public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig { - protected String module = "SwaggerPetstore"; - protected String invokerPackage; - protected String eggPackage; + protected String packageName = null; + protected String packageVersion = null; public PythonClientCodegen() { super(); - eggPackage = module + "-python"; - - invokerPackage = eggPackage + File.separatorChar + module; - + modelPackage = "models"; + apiPackage = "api"; outputFolder = "generated-code" + File.separatorChar + "python"; modelTemplateFiles.put("model.mustache", ".py"); apiTemplateFiles.put("api.mustache", ".py"); templateDir = "python"; - apiPackage = invokerPackage + File.separatorChar + "apis"; - modelPackage = invokerPackage + File.separatorChar + "models"; - languageSpecificPrimitives.clear(); languageSpecificPrimitives.add("int"); languageSpecificPrimitives.add("float"); @@ -60,14 +55,45 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig "print", "class", "exec", "in", "raise", "continue", "finally", "is", "return", "def", "for", "lambda", "try")); - additionalProperties.put("module", module); + cliOptions.clear(); + cliOptions.add(new CliOption("packageName", "python package name, default: SwaggerClient")); + cliOptions.add(new CliOption("packageVersion", "python package version, default: 1.0.0")); + } - supportingFiles.add(new SupportingFile("README.mustache", eggPackage, "README.md")); - supportingFiles.add(new SupportingFile("setup.mustache", eggPackage, "setup.py")); - supportingFiles.add(new SupportingFile("api_client.mustache", invokerPackage, "api_client.py")); - supportingFiles.add(new SupportingFile("rest.mustache", invokerPackage, "rest.py")); - supportingFiles.add(new SupportingFile("configuration.mustache", invokerPackage, "configuration.py")); - supportingFiles.add(new SupportingFile("__init__package.mustache", invokerPackage, "__init__.py")); + @Override + public void processOpts() { + super.processOpts(); + + if (additionalProperties.containsKey("packageName")) { + setPackageName((String) additionalProperties.get("packageName")); + } + else { + setPackageName("SwaggerClient"); + } + setPackageName(generatePackageName(packageName)); + + if (additionalProperties.containsKey("packageVersion")) { + setPackageVersion((String) additionalProperties.get("packageVersion")); + } + else { + setPackageVersion("1.0.0"); + } + + additionalProperties.put("packageName", packageName); + additionalProperties.put("packageVersion", packageVersion); + + String baseFolder = packageName + "_python"; + String swaggerFoler = baseFolder + File.separatorChar + packageName; + + modelPackage = swaggerFoler + File.separatorChar + "models"; + apiPackage = swaggerFoler + File.separatorChar + "apis"; + + supportingFiles.add(new SupportingFile("README.mustache", baseFolder, "README.md")); + supportingFiles.add(new SupportingFile("setup.mustache", baseFolder, "setup.py")); + supportingFiles.add(new SupportingFile("api_client.mustache", swaggerFoler, "api_client.py")); + supportingFiles.add(new SupportingFile("rest.mustache", swaggerFoler, "rest.py")); + supportingFiles.add(new SupportingFile("configuration.mustache", swaggerFoler, "configuration.py")); + supportingFiles.add(new SupportingFile("__init__package.mustache", swaggerFoler, "__init__.py")); supportingFiles.add(new SupportingFile("__init__model.mustache", modelPackage, "__init__.py")); supportingFiles.add(new SupportingFile("__init__api.mustache", apiPackage, "__init__.py")); } @@ -225,4 +251,23 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig return underscore(operationId); } + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public void setPackageVersion(String packageVersion) { + this.packageVersion = packageVersion; + } + + /** + * Generate Python package name from String `packageName` + * + * (PEP 0008) Python packages should also have short, all-lowercase names, + * although the use of underscores is discouraged. + */ + public String generatePackageName(String packageName) { + return underscore(packageName.replaceAll("[^\\w]+", "")); + } } + + diff --git a/modules/swagger-codegen/src/main/resources/python/setup.mustache b/modules/swagger-codegen/src/main/resources/python/setup.mustache index f1ba52d2930..af4fa69baf3 100644 --- a/modules/swagger-codegen/src/main/resources/python/setup.mustache +++ b/modules/swagger-codegen/src/main/resources/python/setup.mustache @@ -1,6 +1,9 @@ import sys from setuptools import setup, find_packages +NAME = "{{packageName}}" +VERSION = "{{packageVersion}}" + {{#apiInfo}}{{#apis}}{{^hasMore}} # To install the library, open a Terminal shell, then run this @@ -15,8 +18,8 @@ from setuptools import setup, find_packages REQUIRES = ["urllib3 >= 1.10", "six >= 1.9", "certifi"] setup( - name="{{module}}", - version="{{version}}", + name=NAME, + version=VERSION, description="{{appName}}", author_email="{{infoEmail}}", url="{{infoUrl}}", diff --git a/samples/client/petstore/python/SwaggerPetstore-python/Makefile b/samples/client/petstore/python/swagger_client_python/Makefile similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/Makefile rename to samples/client/petstore/python/swagger_client_python/Makefile diff --git a/samples/client/petstore/python/SwaggerPetstore-python/README.md b/samples/client/petstore/python/swagger_client_python/README.md similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/README.md rename to samples/client/petstore/python/swagger_client_python/README.md diff --git a/samples/client/petstore/python/SwaggerPetstore-python/dev-requirements.txt b/samples/client/petstore/python/swagger_client_python/dev-requirements.txt similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/dev-requirements.txt rename to samples/client/petstore/python/swagger_client_python/dev-requirements.txt diff --git a/samples/client/petstore/python/SwaggerPetstore-python/pom.xml b/samples/client/petstore/python/swagger_client_python/pom.xml similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/pom.xml rename to samples/client/petstore/python/swagger_client_python/pom.xml diff --git a/samples/client/petstore/python/SwaggerPetstore-python/setup.cfg b/samples/client/petstore/python/swagger_client_python/setup.cfg similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/setup.cfg rename to samples/client/petstore/python/swagger_client_python/setup.cfg diff --git a/samples/client/petstore/python/SwaggerPetstore-python/setup.py b/samples/client/petstore/python/swagger_client_python/setup.py similarity index 92% rename from samples/client/petstore/python/SwaggerPetstore-python/setup.py rename to samples/client/petstore/python/swagger_client_python/setup.py index fbd738be680..4232c3992b9 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/setup.py +++ b/samples/client/petstore/python/swagger_client_python/setup.py @@ -1,6 +1,9 @@ import sys from setuptools import setup, find_packages +NAME = "swagger_client" +VERSION = "1.0.0" + # To install the library, open a Terminal shell, then run this @@ -15,8 +18,8 @@ from setuptools import setup, find_packages REQUIRES = ["urllib3 >= 1.10", "six >= 1.9", "certifi"] setup( - name="SwaggerPetstore", - version="1.0.0", + name=NAME, + version=VERSION, description="Swagger Petstore", author_email="apiteam@swagger.io", url="", diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/__init__.py b/samples/client/petstore/python/swagger_client_python/swagger_client/__init__.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/__init__.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/__init__.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/api_client.py b/samples/client/petstore/python/swagger_client_python/swagger_client/api_client.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/api_client.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/api_client.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/__init__.py b/samples/client/petstore/python/swagger_client_python/swagger_client/apis/__init__.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/__init__.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/apis/__init__.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py b/samples/client/petstore/python/swagger_client_python/swagger_client/apis/pet_api.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/pet_api.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/apis/pet_api.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py b/samples/client/petstore/python/swagger_client_python/swagger_client/apis/store_api.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/store_api.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/apis/store_api.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py b/samples/client/petstore/python/swagger_client_python/swagger_client/apis/user_api.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/apis/user_api.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/apis/user_api.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/configuration.py b/samples/client/petstore/python/swagger_client_python/swagger_client/configuration.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/configuration.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/configuration.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/__init__.py b/samples/client/petstore/python/swagger_client_python/swagger_client/models/__init__.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/__init__.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/models/__init__.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/category.py b/samples/client/petstore/python/swagger_client_python/swagger_client/models/category.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/category.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/models/category.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/order.py b/samples/client/petstore/python/swagger_client_python/swagger_client/models/order.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/order.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/models/order.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/pet.py b/samples/client/petstore/python/swagger_client_python/swagger_client/models/pet.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/pet.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/models/pet.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/tag.py b/samples/client/petstore/python/swagger_client_python/swagger_client/models/tag.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/tag.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/models/tag.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/user.py b/samples/client/petstore/python/swagger_client_python/swagger_client/models/user.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/models/user.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/models/user.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/rest.py b/samples/client/petstore/python/swagger_client_python/swagger_client/rest.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/SwaggerPetstore/rest.py rename to samples/client/petstore/python/swagger_client_python/swagger_client/rest.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/testfiles/foo.png b/samples/client/petstore/python/swagger_client_python/testfiles/foo.png similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/testfiles/foo.png rename to samples/client/petstore/python/swagger_client_python/testfiles/foo.png diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tests/__init__.py b/samples/client/petstore/python/swagger_client_python/tests/__init__.py similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/tests/__init__.py rename to samples/client/petstore/python/swagger_client_python/tests/__init__.py diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py b/samples/client/petstore/python/swagger_client_python/tests/test_api_client.py similarity index 85% rename from samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py rename to samples/client/petstore/python/swagger_client_python/tests/test_api_client.py index 42d838417fd..d18008f5575 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_client.py +++ b/samples/client/petstore/python/swagger_client_python/tests/test_api_client.py @@ -11,8 +11,8 @@ import os import time import unittest -import SwaggerPetstore -import SwaggerPetstore.configuration +import swagger_client +import swagger_client.configuration HOST = 'http://petstore.swagger.io/v2' @@ -20,20 +20,20 @@ HOST = 'http://petstore.swagger.io/v2' class ApiClientTests(unittest.TestCase): def setUp(self): - self.api_client = SwaggerPetstore.ApiClient(HOST) + self.api_client = swagger_client.ApiClient(HOST) def test_configuration(self): - SwaggerPetstore.configuration.api_key['api_key'] = '123456' - SwaggerPetstore.configuration.api_key_prefix['api_key'] = 'PREFIX' - SwaggerPetstore.configuration.username = 'test_username' - SwaggerPetstore.configuration.password = 'test_password' + swagger_client.configuration.api_key['api_key'] = '123456' + swagger_client.configuration.api_key_prefix['api_key'] = 'PREFIX' + swagger_client.configuration.username = 'test_username' + swagger_client.configuration.password = 'test_password' header_params = {'test1': 'value1'} query_params = {'test2': 'value2'} auth_settings = ['api_key', 'unknown'] # test prefix - self.assertEqual('PREFIX', SwaggerPetstore.configuration.api_key_prefix['api_key']) + self.assertEqual('PREFIX', swagger_client.configuration.api_key_prefix['api_key']) # update parameters based on auth setting self.api_client.update_params_for_auth(header_params, query_params, auth_settings) @@ -44,8 +44,8 @@ class ApiClientTests(unittest.TestCase): self.assertEqual(query_params['test2'], 'value2') # test basic auth - self.assertEqual('test_username', SwaggerPetstore.configuration.username) - self.assertEqual('test_password', SwaggerPetstore.configuration.password) + self.assertEqual('test_username', swagger_client.configuration.username) + self.assertEqual('test_password', swagger_client.configuration.password) def test_select_header_accept(self): accepts = ['APPLICATION/JSON', 'APPLICATION/XML'] diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_exception.py b/samples/client/petstore/python/swagger_client_python/tests/test_api_exception.py similarity index 85% rename from samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_exception.py rename to samples/client/petstore/python/swagger_client_python/tests/test_api_exception.py index d1b786241e8..f3d00cb10dc 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_api_exception.py +++ b/samples/client/petstore/python/swagger_client_python/tests/test_api_exception.py @@ -3,7 +3,7 @@ """ Run the tests. $ pip install nose (optional) -$ cd SwaggerPetstore-python +$ cd swagger_client-python $ nosetests -v """ @@ -11,25 +11,25 @@ import os import time import unittest -import SwaggerPetstore -from SwaggerPetstore.rest import ApiException +import swagger_client +from swagger_client.rest import ApiException class ApiExceptionTests(unittest.TestCase): def setUp(self): - self.api_client = SwaggerPetstore.ApiClient() - self.pet_api = SwaggerPetstore.PetApi(self.api_client) + self.api_client = swagger_client.ApiClient() + self.pet_api = swagger_client.PetApi(self.api_client) self.setUpModels() def setUpModels(self): - self.category = SwaggerPetstore.Category() + self.category = swagger_client.Category() self.category.id = int(time.time()) self.category.name = "dog" - self.tag = SwaggerPetstore.Tag() + self.tag = swagger_client.Tag() self.tag.id = int(time.time()) self.tag.name = "blank" - self.pet = SwaggerPetstore.Pet() + self.pet = swagger_client.Pet() self.pet.id = int(time.time()) self.pet.name = "hello kity" self.pet.photo_urls = ["http://foo.bar.com/1", "http://foo.bar.com/2"] diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_pet_api.py b/samples/client/petstore/python/swagger_client_python/tests/test_pet_api.py similarity index 84% rename from samples/client/petstore/python/SwaggerPetstore-python/tests/test_pet_api.py rename to samples/client/petstore/python/swagger_client_python/tests/test_pet_api.py index 3bf18607729..5397c0b50ef 100644 --- a/samples/client/petstore/python/SwaggerPetstore-python/tests/test_pet_api.py +++ b/samples/client/petstore/python/swagger_client_python/tests/test_pet_api.py @@ -3,7 +3,7 @@ """ Run the tests. $ pip install nose (optional) -$ cd SwaggerPetstore-python +$ cd swagger_client-python $ nosetests -v """ @@ -11,8 +11,8 @@ import os import time import unittest -import SwaggerPetstore -from SwaggerPetstore.rest import ApiException +import swagger_client +from swagger_client.rest import ApiException HOST = 'http://petstore.swagger.io/v2' @@ -20,8 +20,8 @@ HOST = 'http://petstore.swagger.io/v2' class PetApiTests(unittest.TestCase): def setUp(self): - self.api_client = SwaggerPetstore.ApiClient(HOST) - self.pet_api = SwaggerPetstore.PetApi(self.api_client) + self.api_client = swagger_client.ApiClient(HOST) + self.pet_api = swagger_client.PetApi(self.api_client) self.setUpModels() self.setUpFiles() @@ -30,13 +30,13 @@ class PetApiTests(unittest.TestCase): time.sleep(1) def setUpModels(self): - self.category = SwaggerPetstore.Category() + self.category = swagger_client.Category() self.category.id = int(time.time()) self.category.name = "dog" - self.tag = SwaggerPetstore.Tag() + self.tag = swagger_client.Tag() self.tag.id = int(time.time()) self.tag.name = "blank" - self.pet = SwaggerPetstore.Pet() + self.pet = swagger_client.Pet() self.pet.id = int(time.time()) self.pet.name = "hello kity" self.pet.photo_urls = ["http://foo.bar.com/1", "http://foo.bar.com/2"] @@ -50,22 +50,22 @@ class PetApiTests(unittest.TestCase): self.foo = os.path.join(self.test_file_dir, "foo.png") def test_create_api_instance(self): - pet_api = SwaggerPetstore.PetApi() - pet_api2 = SwaggerPetstore.PetApi() - api_client3 = SwaggerPetstore.ApiClient() + pet_api = swagger_client.PetApi() + pet_api2 = swagger_client.PetApi() + api_client3 = swagger_client.ApiClient() api_client3.user_agent = 'api client 3' - api_client4 = SwaggerPetstore.ApiClient() + api_client4 = swagger_client.ApiClient() api_client4.user_agent = 'api client 4' - pet_api3 = SwaggerPetstore.PetApi(api_client3) + pet_api3 = swagger_client.PetApi(api_client3) # same default api client self.assertEqual(pet_api.api_client, pet_api2.api_client) # confirm using the default api client in the config module - self.assertEqual(pet_api.api_client, SwaggerPetstore.configuration.api_client) + self.assertEqual(pet_api.api_client, swagger_client.configuration.api_client) # 2 different api clients are not the same self.assertNotEqual(api_client3, api_client4) # customized pet api not using the default api client - self.assertNotEqual(pet_api3.api_client, SwaggerPetstore.configuration.api_client) + self.assertNotEqual(pet_api3.api_client, swagger_client.configuration.api_client) # customized pet api not using the old pet api's api client self.assertNotEqual(pet_api3.api_client, pet_api2.api_client) diff --git a/samples/client/petstore/python/SwaggerPetstore-python/tox.ini b/samples/client/petstore/python/swagger_client_python/tox.ini similarity index 100% rename from samples/client/petstore/python/SwaggerPetstore-python/tox.ini rename to samples/client/petstore/python/swagger_client_python/tox.ini From 5d19ef6146ff926cd4fe94078ceb5bbfd771fa46 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Fri, 12 Jun 2015 18:22:24 +0800 Subject: [PATCH 08/67] Generate the python into `python/` folder directly --- .../codegen/languages/PythonClientCodegen.java | 7 +++---- .../python/{swagger_client_python => }/Makefile | 0 .../python/{swagger_client_python => }/README.md | 0 .../dev-requirements.txt | 0 .../python/{swagger_client_python => }/pom.xml | 0 .../python/{swagger_client_python => }/setup.cfg | 0 .../python/{swagger_client_python => }/setup.py | 0 .../swagger_client/__init__.py | 0 .../swagger_client/api_client.py | 0 .../swagger_client/apis/__init__.py | 0 .../swagger_client/apis/pet_api.py | 0 .../swagger_client/apis/store_api.py | 0 .../swagger_client/apis/user_api.py | 0 .../swagger_client/configuration.py | 0 .../swagger_client/models/__init__.py | 0 .../swagger_client/models/category.py | 0 .../swagger_client/models/order.py | 0 .../swagger_client/models/pet.py | 0 .../swagger_client/models/tag.py | 0 .../swagger_client/models/user.py | 0 .../swagger_client/rest.py | 0 .../{swagger_client_python => }/testfiles/foo.png | Bin .../{swagger_client_python => }/tests/__init__.py | 0 .../tests/test_api_client.py | 0 .../tests/test_api_exception.py | 0 .../tests/test_pet_api.py | 0 .../python/{swagger_client_python => }/tox.ini | 0 27 files changed, 3 insertions(+), 4 deletions(-) rename samples/client/petstore/python/{swagger_client_python => }/Makefile (100%) rename samples/client/petstore/python/{swagger_client_python => }/README.md (100%) rename samples/client/petstore/python/{swagger_client_python => }/dev-requirements.txt (100%) rename samples/client/petstore/python/{swagger_client_python => }/pom.xml (100%) rename samples/client/petstore/python/{swagger_client_python => }/setup.cfg (100%) rename samples/client/petstore/python/{swagger_client_python => }/setup.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/__init__.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/api_client.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/apis/__init__.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/apis/pet_api.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/apis/store_api.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/apis/user_api.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/configuration.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/models/__init__.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/models/category.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/models/order.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/models/pet.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/models/tag.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/models/user.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/swagger_client/rest.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/testfiles/foo.png (100%) rename samples/client/petstore/python/{swagger_client_python => }/tests/__init__.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/tests/test_api_client.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/tests/test_api_exception.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/tests/test_pet_api.py (100%) rename samples/client/petstore/python/{swagger_client_python => }/tox.ini (100%) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java index e5a3b0810b2..030e19c1a31 100755 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java @@ -82,14 +82,13 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig additionalProperties.put("packageName", packageName); additionalProperties.put("packageVersion", packageVersion); - String baseFolder = packageName + "_python"; - String swaggerFoler = baseFolder + File.separatorChar + packageName; + String swaggerFoler = packageName; modelPackage = swaggerFoler + File.separatorChar + "models"; apiPackage = swaggerFoler + File.separatorChar + "apis"; - supportingFiles.add(new SupportingFile("README.mustache", baseFolder, "README.md")); - supportingFiles.add(new SupportingFile("setup.mustache", baseFolder, "setup.py")); + supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); + supportingFiles.add(new SupportingFile("setup.mustache", "", "setup.py")); supportingFiles.add(new SupportingFile("api_client.mustache", swaggerFoler, "api_client.py")); supportingFiles.add(new SupportingFile("rest.mustache", swaggerFoler, "rest.py")); supportingFiles.add(new SupportingFile("configuration.mustache", swaggerFoler, "configuration.py")); diff --git a/samples/client/petstore/python/swagger_client_python/Makefile b/samples/client/petstore/python/Makefile similarity index 100% rename from samples/client/petstore/python/swagger_client_python/Makefile rename to samples/client/petstore/python/Makefile diff --git a/samples/client/petstore/python/swagger_client_python/README.md b/samples/client/petstore/python/README.md similarity index 100% rename from samples/client/petstore/python/swagger_client_python/README.md rename to samples/client/petstore/python/README.md diff --git a/samples/client/petstore/python/swagger_client_python/dev-requirements.txt b/samples/client/petstore/python/dev-requirements.txt similarity index 100% rename from samples/client/petstore/python/swagger_client_python/dev-requirements.txt rename to samples/client/petstore/python/dev-requirements.txt diff --git a/samples/client/petstore/python/swagger_client_python/pom.xml b/samples/client/petstore/python/pom.xml similarity index 100% rename from samples/client/petstore/python/swagger_client_python/pom.xml rename to samples/client/petstore/python/pom.xml diff --git a/samples/client/petstore/python/swagger_client_python/setup.cfg b/samples/client/petstore/python/setup.cfg similarity index 100% rename from samples/client/petstore/python/swagger_client_python/setup.cfg rename to samples/client/petstore/python/setup.cfg diff --git a/samples/client/petstore/python/swagger_client_python/setup.py b/samples/client/petstore/python/setup.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/setup.py rename to samples/client/petstore/python/setup.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/__init__.py b/samples/client/petstore/python/swagger_client/__init__.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/__init__.py rename to samples/client/petstore/python/swagger_client/__init__.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/api_client.py b/samples/client/petstore/python/swagger_client/api_client.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/api_client.py rename to samples/client/petstore/python/swagger_client/api_client.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/apis/__init__.py b/samples/client/petstore/python/swagger_client/apis/__init__.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/apis/__init__.py rename to samples/client/petstore/python/swagger_client/apis/__init__.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/apis/pet_api.py b/samples/client/petstore/python/swagger_client/apis/pet_api.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/apis/pet_api.py rename to samples/client/petstore/python/swagger_client/apis/pet_api.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/apis/store_api.py b/samples/client/petstore/python/swagger_client/apis/store_api.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/apis/store_api.py rename to samples/client/petstore/python/swagger_client/apis/store_api.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/apis/user_api.py b/samples/client/petstore/python/swagger_client/apis/user_api.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/apis/user_api.py rename to samples/client/petstore/python/swagger_client/apis/user_api.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/configuration.py b/samples/client/petstore/python/swagger_client/configuration.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/configuration.py rename to samples/client/petstore/python/swagger_client/configuration.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/models/__init__.py b/samples/client/petstore/python/swagger_client/models/__init__.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/models/__init__.py rename to samples/client/petstore/python/swagger_client/models/__init__.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/models/category.py b/samples/client/petstore/python/swagger_client/models/category.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/models/category.py rename to samples/client/petstore/python/swagger_client/models/category.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/models/order.py b/samples/client/petstore/python/swagger_client/models/order.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/models/order.py rename to samples/client/petstore/python/swagger_client/models/order.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/models/pet.py b/samples/client/petstore/python/swagger_client/models/pet.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/models/pet.py rename to samples/client/petstore/python/swagger_client/models/pet.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/models/tag.py b/samples/client/petstore/python/swagger_client/models/tag.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/models/tag.py rename to samples/client/petstore/python/swagger_client/models/tag.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/models/user.py b/samples/client/petstore/python/swagger_client/models/user.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/models/user.py rename to samples/client/petstore/python/swagger_client/models/user.py diff --git a/samples/client/petstore/python/swagger_client_python/swagger_client/rest.py b/samples/client/petstore/python/swagger_client/rest.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/swagger_client/rest.py rename to samples/client/petstore/python/swagger_client/rest.py diff --git a/samples/client/petstore/python/swagger_client_python/testfiles/foo.png b/samples/client/petstore/python/testfiles/foo.png similarity index 100% rename from samples/client/petstore/python/swagger_client_python/testfiles/foo.png rename to samples/client/petstore/python/testfiles/foo.png diff --git a/samples/client/petstore/python/swagger_client_python/tests/__init__.py b/samples/client/petstore/python/tests/__init__.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/tests/__init__.py rename to samples/client/petstore/python/tests/__init__.py diff --git a/samples/client/petstore/python/swagger_client_python/tests/test_api_client.py b/samples/client/petstore/python/tests/test_api_client.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/tests/test_api_client.py rename to samples/client/petstore/python/tests/test_api_client.py diff --git a/samples/client/petstore/python/swagger_client_python/tests/test_api_exception.py b/samples/client/petstore/python/tests/test_api_exception.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/tests/test_api_exception.py rename to samples/client/petstore/python/tests/test_api_exception.py diff --git a/samples/client/petstore/python/swagger_client_python/tests/test_pet_api.py b/samples/client/petstore/python/tests/test_pet_api.py similarity index 100% rename from samples/client/petstore/python/swagger_client_python/tests/test_pet_api.py rename to samples/client/petstore/python/tests/test_pet_api.py diff --git a/samples/client/petstore/python/swagger_client_python/tox.ini b/samples/client/petstore/python/tox.ini similarity index 100% rename from samples/client/petstore/python/swagger_client_python/tox.ini rename to samples/client/petstore/python/tox.ini From 62f4c252f2eb01c58350f27d70c35aaeaf17ec8c Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 16 Jun 2015 09:44:18 +0800 Subject: [PATCH 09/67] Update python codegen. * Update config-help message. * Do not sanitize packageName to underscore format. --- .../io/swagger/codegen/languages/PythonClientCodegen.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java index 030e19c1a31..c901462ca48 100755 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java @@ -56,7 +56,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig "return", "def", "for", "lambda", "try")); cliOptions.clear(); - cliOptions.add(new CliOption("packageName", "python package name, default: SwaggerClient")); + cliOptions.add(new CliOption("packageName", "python package name, default: swagger_client")); cliOptions.add(new CliOption("packageVersion", "python package version, default: 1.0.0")); } @@ -68,9 +68,8 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig setPackageName((String) additionalProperties.get("packageName")); } else { - setPackageName("SwaggerClient"); + setPackageName("swagger_client"); } - setPackageName(generatePackageName(packageName)); if (additionalProperties.containsKey("packageVersion")) { setPackageVersion((String) additionalProperties.get("packageVersion")); From 194c8ff71deb1382c1e5547b877f6f99f0191e07 Mon Sep 17 00:00:00 2001 From: geekerzp Date: Tue, 16 Jun 2015 15:29:10 +0800 Subject: [PATCH 10/67] Update config-help message of python client --- .../java/io/swagger/codegen/languages/PythonClientCodegen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java index c901462ca48..cdafa337c21 100755 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java @@ -56,7 +56,7 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig "return", "def", "for", "lambda", "try")); cliOptions.clear(); - cliOptions.add(new CliOption("packageName", "python package name, default: swagger_client")); + cliOptions.add(new CliOption("packageName", "python package name (convension: under_score), default: swagger_client")); cliOptions.add(new CliOption("packageVersion", "python package version, default: 1.0.0")); } From 449ba4f64470592e0c08035a877919a5f47f0a0b Mon Sep 17 00:00:00 2001 From: Martin Hardorf Date: Thu, 18 Jun 2015 12:42:04 +0200 Subject: [PATCH 11/67] Fixed required parameters for APIs in TypeScript --- .../resources/TypeScript-Angular/api.mustache | 10 +++++----- .../resources/TypeScript-node/api.mustache | 10 +++++----- .../petstore/typescript-angular/api/PetApi.ts | 20 +++++++++++++++++++ .../typescript-angular/api/StoreApi.ts | 10 ++++++++++ .../typescript-angular/api/UserApi.ts | 15 ++++++++++++++ .../petstore/typescript-node/api/PetApi.ts | 20 +++++++++++++++++++ .../petstore/typescript-node/api/StoreApi.ts | 10 ++++++++++ .../petstore/typescript-node/api/UserApi.ts | 15 ++++++++++++++ 8 files changed, 100 insertions(+), 10 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache index 3b53e816891..1095667b245 100644 --- a/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache +++ b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache @@ -29,12 +29,12 @@ module {{package}} { {{/pathParams}} var queryParameters: any = {}; var headers: any = {}; - {{#requiredParamCount}} - // verify required params are set - if ({{/requiredParamCount}}{{#requiredParams}} !{{paramName}} {{#hasMore}}|| {{/hasMore}}{{/requiredParams}}{{#requiredParamCount}}) { - throw new Error('Missing required parameter: {{¶mName}}'); + {{#allParams}}{{#required}} + // verify required parameter '{{paramName}}' is set + if (!{{paramName}}) { + throw new Error('Missing required parameter {{paramName}} when calling {{nickname}}'); } - {{/requiredParamCount}} + {{/required}}{{/allParams}} {{#queryParams}}if ({{paramName}} !== undefined) { queryParameters['{{paramName}}'] = {{paramName}}; }{{/queryParams}} diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache index 4b329799ad5..156ad63f72d 100644 --- a/modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache +++ b/modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache @@ -26,12 +26,12 @@ export class {{classname}} { var queryParameters: any = {}; var headers: any = {}; - {{#requiredParamCount}} - // verify required params are set - if ({{/requiredParamCount}}{{#requiredParams}} !{{paramName}} {{#hasMore}}|| {{/hasMore}}{{/requiredParams}}{{#requiredParamCount}}) { - throw new Error('Missing required parameter: {{¶mName}}'); + {{#allParams}}{{#required}} + // verify required parameter '{{paramName}}' is set + if (!{{paramName}}) { + throw new Error('Missing required parameter {{paramName}} when calling {{nickname}}'); } - {{/requiredParamCount}} + {{/required}}{{/allParams}} {{#queryParams}}if ({{paramName}} !== undefined) { queryParameters['{{paramName}}'] = {{paramName}}; diff --git a/samples/client/petstore/typescript-angular/api/PetApi.ts b/samples/client/petstore/typescript-angular/api/PetApi.ts index 2c5f2a25b6d..d294cfbebbc 100644 --- a/samples/client/petstore/typescript-angular/api/PetApi.ts +++ b/samples/client/petstore/typescript-angular/api/PetApi.ts @@ -143,6 +143,11 @@ module api { var queryParameters: any = {}; var headers: any = {}; + // verify required parameter 'petId' is set + if (!petId) { + throw new Error('Missing required parameter petId when calling getPetById'); + } + var httpRequestParams: any = { @@ -173,6 +178,11 @@ module api { var queryParameters: any = {}; var headers: any = {}; + // verify required parameter 'petId' is set + if (!petId) { + throw new Error('Missing required parameter petId when calling updatePetWithForm'); + } + var httpRequestParams: any = { @@ -203,6 +213,11 @@ module api { var queryParameters: any = {}; var headers: any = {}; + // verify required parameter 'petId' is set + if (!petId) { + throw new Error('Missing required parameter petId when calling deletePet'); + } + headerParams['apiKey'] = apiKey; var httpRequestParams: any = { @@ -233,6 +248,11 @@ module api { var queryParameters: any = {}; var headers: any = {}; + // verify required parameter 'petId' is set + if (!petId) { + throw new Error('Missing required parameter petId when calling uploadFile'); + } + var httpRequestParams: any = { diff --git a/samples/client/petstore/typescript-angular/api/StoreApi.ts b/samples/client/petstore/typescript-angular/api/StoreApi.ts index e4c9e48e0e9..e8c85b00c45 100644 --- a/samples/client/petstore/typescript-angular/api/StoreApi.ts +++ b/samples/client/petstore/typescript-angular/api/StoreApi.ts @@ -82,6 +82,11 @@ module api { var queryParameters: any = {}; var headers: any = {}; + // verify required parameter 'orderId' is set + if (!orderId) { + throw new Error('Missing required parameter orderId when calling getOrderById'); + } + var httpRequestParams: any = { @@ -112,6 +117,11 @@ module api { var queryParameters: any = {}; var headers: any = {}; + // verify required parameter 'orderId' is set + if (!orderId) { + throw new Error('Missing required parameter orderId when calling deleteOrder'); + } + var httpRequestParams: any = { diff --git a/samples/client/petstore/typescript-angular/api/UserApi.ts b/samples/client/petstore/typescript-angular/api/UserApi.ts index dfbe9032dba..40d82f73852 100644 --- a/samples/client/petstore/typescript-angular/api/UserApi.ts +++ b/samples/client/petstore/typescript-angular/api/UserApi.ts @@ -172,6 +172,11 @@ module api { var queryParameters: any = {}; var headers: any = {}; + // verify required parameter 'username' is set + if (!username) { + throw new Error('Missing required parameter username when calling getUserByName'); + } + var httpRequestParams: any = { @@ -202,6 +207,11 @@ module api { var queryParameters: any = {}; var headers: any = {}; + // verify required parameter 'username' is set + if (!username) { + throw new Error('Missing required parameter username when calling updateUser'); + } + var httpRequestParams: any = { @@ -233,6 +243,11 @@ module api { var queryParameters: any = {}; var headers: any = {}; + // verify required parameter 'username' is set + if (!username) { + throw new Error('Missing required parameter username when calling deleteUser'); + } + var httpRequestParams: any = { diff --git a/samples/client/petstore/typescript-node/api/PetApi.ts b/samples/client/petstore/typescript-node/api/PetApi.ts index c948f8036e6..02605f2c8a8 100644 --- a/samples/client/petstore/typescript-node/api/PetApi.ts +++ b/samples/client/petstore/typescript-node/api/PetApi.ts @@ -193,6 +193,11 @@ export class PetApi { var headers: any = {}; + // verify required parameter 'petId' is set + if (!petId) { + throw new Error('Missing required parameter petId when calling getPetById'); + } + @@ -236,6 +241,11 @@ export class PetApi { var headers: any = {}; + // verify required parameter 'petId' is set + if (!petId) { + throw new Error('Missing required parameter petId when calling updatePetWithForm'); + } + @@ -279,6 +289,11 @@ export class PetApi { var headers: any = {}; + // verify required parameter 'petId' is set + if (!petId) { + throw new Error('Missing required parameter petId when calling deletePet'); + } + @@ -323,6 +338,11 @@ export class PetApi { var headers: any = {}; + // verify required parameter 'petId' is set + if (!petId) { + throw new Error('Missing required parameter petId when calling uploadFile'); + } + diff --git a/samples/client/petstore/typescript-node/api/StoreApi.ts b/samples/client/petstore/typescript-node/api/StoreApi.ts index 1c2c6623523..71cfe106fca 100644 --- a/samples/client/petstore/typescript-node/api/StoreApi.ts +++ b/samples/client/petstore/typescript-node/api/StoreApi.ts @@ -104,6 +104,11 @@ export class StoreApi { var headers: any = {}; + // verify required parameter 'orderId' is set + if (!orderId) { + throw new Error('Missing required parameter orderId when calling getOrderById'); + } + @@ -147,6 +152,11 @@ export class StoreApi { var headers: any = {}; + // verify required parameter 'orderId' is set + if (!orderId) { + throw new Error('Missing required parameter orderId when calling deleteOrder'); + } + diff --git a/samples/client/petstore/typescript-node/api/UserApi.ts b/samples/client/petstore/typescript-node/api/UserApi.ts index fa4365f8edc..ca6fd41c593 100644 --- a/samples/client/petstore/typescript-node/api/UserApi.ts +++ b/samples/client/petstore/typescript-node/api/UserApi.ts @@ -235,6 +235,11 @@ export class UserApi { var headers: any = {}; + // verify required parameter 'username' is set + if (!username) { + throw new Error('Missing required parameter username when calling getUserByName'); + } + @@ -278,6 +283,11 @@ export class UserApi { var headers: any = {}; + // verify required parameter 'username' is set + if (!username) { + throw new Error('Missing required parameter username when calling updateUser'); + } + @@ -322,6 +332,11 @@ export class UserApi { var headers: any = {}; + // verify required parameter 'username' is set + if (!username) { + throw new Error('Missing required parameter username when calling deleteUser'); + } + From 8d18aee2f2222e17f4bd7d4dbba1e4918b5b2e3b Mon Sep 17 00:00:00 2001 From: geekerzp Date: Thu, 18 Jun 2015 22:02:54 +0800 Subject: [PATCH 12/67] Update test case `test_deserialize_to_dict` of python client --- samples/client/petstore/python/tests/test_api_client.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/samples/client/petstore/python/tests/test_api_client.py b/samples/client/petstore/python/tests/test_api_client.py index d18008f5575..d932006c052 100644 --- a/samples/client/petstore/python/tests/test_api_client.py +++ b/samples/client/petstore/python/tests/test_api_client.py @@ -114,7 +114,7 @@ class ApiClientTests(unittest.TestCase): data = self.api_client.deserialize(json, 'dict(str, Pet)') self.assertTrue(isinstance(data, dict)) - self.assertTrue(isinstance(data['pet'], SwaggerPetstore.Pet)) + self.assertTrue(isinstance(data['pet'], swagger_client.Pet)) # dict(str, int) json = { @@ -128,6 +128,3 @@ class ApiClientTests(unittest.TestCase): def test_deserialize_to_object(self): data = self.api_client.deserialize("", "object") self.assertTrue(type(data) == object) - - - From df72188bc0c7e4db21d87b288fb6ae97ab5ccfd5 Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 18 Jun 2015 22:06:59 +0800 Subject: [PATCH 13/67] add cli support to csharp --- .../languages/CSharpClientCodegen.java | 64 +++++++++++++------ .../main/resources/csharp/ApiClient.mustache | 2 +- .../resources/csharp/ApiException.mustache | 2 +- .../resources/csharp/Configuration.mustache | 3 +- .../src/main/resources/csharp/api.mustache | 6 +- .../src/main/resources/csharp/model.mustache | 2 +- samples/client/petstore/csharp/compile.bat | 2 +- .../csharp/io/swagger/client/Configuration.cs | 1 - 8 files changed, 53 insertions(+), 29 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java index a564ec5f883..33ea13b5e31 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/CSharpClientCodegen.java @@ -7,6 +7,7 @@ import io.swagger.codegen.SupportingFile; import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.MapProperty; import io.swagger.models.properties.Property; +import io.swagger.codegen.CliOption; import java.io.File; import java.util.Arrays; @@ -14,15 +15,14 @@ import java.util.HashMap; import java.util.HashSet; public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig { - protected String invokerPackage = "IO.Swagger.Client"; - protected String groupId = "io.swagger"; - protected String artifactId = "swagger-csharp-client"; - protected String artifactVersion = "1.0.0"; - protected String sourceFolder = "src/main/csharp"; + protected String packageName = "IO.Swagger"; + protected String packageVersion = "1.0.0"; + protected String clientPackage = "IO.Swagger.Client"; + protected String sourceFolder = "src" + File.separator + "main" + File.separator + "csharp"; public CSharpClientCodegen() { super(); - outputFolder = "generated-code/csharp"; + outputFolder = "generated-code" + File.separator + "csharp"; modelTemplateFiles.put("model.mustache", ".cs"); apiTemplateFiles.put("api.mustache", ".cs"); templateDir = "csharp"; @@ -34,17 +34,6 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig "abstract", "as", "base", "bool", "break", "byte", "case", "catch", "char", "checked", "class", "const", "continue", "decimal", "default", "delegate", "do", "double", "else", "enum", "event", "explicit", "extern", "false", "finally", "fixed", "float", "for", "foreach", "goto", "if", "implicit", "in", "int", "interface", "internal", "is", "lock", "long", "namespace", "new", "null", "object", "operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "return", "sbyte", "sealed", "short", "sizeof", "stackalloc", "static", "string", "struct", "switch", "this", "throw", "true", "try", "typeof", "uint", "ulong", "unchecked", "unsafe", "ushort", "using", "virtual", "void", "volatile", "while") ); - additionalProperties.put("invokerPackage", invokerPackage); - - supportingFiles.add(new SupportingFile("Configuration.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "Configuration.cs")); - supportingFiles.add(new SupportingFile("ApiClient.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiClient.cs")); - supportingFiles.add(new SupportingFile("ApiException.mustache", - (sourceFolder + File.separator + invokerPackage).replace(".", java.io.File.separator), "ApiException.cs")); - supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll")); - supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll")); - supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat")); languageSpecificPrimitives = new HashSet( Arrays.asList( @@ -85,6 +74,43 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig typeMapping.put("map", "Dictionary"); typeMapping.put("object", "Object"); + cliOptions.clear(); + cliOptions.add(new CliOption("packageName", "C# package name (convention: Camel.Case), default: IO.Swagger")); + cliOptions.add(new CliOption("packageVersion", "C# package version, default: 1.0.0")); + + } + + @Override + public void processOpts() { + super.processOpts(); + + if (additionalProperties.containsKey("packageVersion")) { + packageVersion = (String) additionalProperties.get("packageVersion"); + } else { + additionalProperties.put("packageVersion", packageVersion); + } + + if (additionalProperties.containsKey("packageName")) { + packageName = (String) additionalProperties.get("packageName"); + apiPackage = packageName + ".Api"; + modelPackage = packageName + ".Model"; + clientPackage = packageName + ".Client"; + } else { + additionalProperties.put("packageName", packageName); + } + + additionalProperties.put("clientPackage", clientPackage); + + supportingFiles.add(new SupportingFile("Configuration.mustache", + (sourceFolder + File.separator + clientPackage).replace(".", java.io.File.separator), "Configuration.cs")); + supportingFiles.add(new SupportingFile("ApiClient.mustache", + (sourceFolder + File.separator + clientPackage).replace(".", java.io.File.separator), "ApiClient.cs")); + supportingFiles.add(new SupportingFile("ApiException.mustache", + (sourceFolder + File.separator + clientPackage).replace(".", java.io.File.separator), "ApiException.cs")); + supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll")); + supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll")); + supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat")); + } public CodegenType getTag() { @@ -106,11 +132,11 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig @Override public String apiFileFolder() { - return (outputFolder + "/" + sourceFolder + "/" + apiPackage().replace('.', '/')).replace('.', File.separatorChar); + return (outputFolder + File.separator + sourceFolder + File.separator + apiPackage()).replace('.', File.separatorChar); } public String modelFileFolder() { - return (outputFolder + "/" + sourceFolder + "/" + modelPackage().replace('.', '/')).replace('.', File.separatorChar); + return (outputFolder + File.separator + sourceFolder + File.separator + modelPackage()).replace('.', File.separatorChar); } @Override diff --git a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache index ad57cffdf34..c6f57bd4a37 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/ApiClient.mustache @@ -8,7 +8,7 @@ using System.Threading.Tasks; using Newtonsoft.Json; using RestSharp; -namespace {{invokerPackage}} { +namespace {{packageName}}.Client { /// /// API client is mainly responible for making the HTTP call to the API backend /// diff --git a/modules/swagger-codegen/src/main/resources/csharp/ApiException.mustache b/modules/swagger-codegen/src/main/resources/csharp/ApiException.mustache index 38a340be249..65c6193b84f 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/ApiException.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/ApiException.mustache @@ -1,6 +1,6 @@ using System; -namespace {{invokerPackage}} { +namespace {{packageName}}.Client { /// /// API Exception /// diff --git a/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache b/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache index 1f5c00a356d..86e35441493 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache @@ -4,9 +4,8 @@ using System.IO; using System.Linq; using System.Net; using System.Text; -using {{invokerPackage}}; -namespace {{invokerPackage}} { +namespace {{packageName}}.Client { /// /// Represents a set of configuration settings /// diff --git a/modules/swagger-codegen/src/main/resources/csharp/api.mustache b/modules/swagger-codegen/src/main/resources/csharp/api.mustache index e22d5517ab5..652d15a30b3 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/api.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/api.mustache @@ -2,12 +2,12 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; using RestSharp; -using {{invokerPackage}}; -using {{modelPackage}}; +using {{packageName}}.Client; +using {{packageName}}.Model; {{#imports}} {{/imports}} -namespace {{package}} { +namespace {{packageName}}.Api { {{#operations}} public interface I{{classname}} { diff --git a/modules/swagger-codegen/src/main/resources/csharp/model.mustache b/modules/swagger-codegen/src/main/resources/csharp/model.mustache index ce0e62de192..0d86e0e2b99 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/model.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/model.mustache @@ -7,7 +7,7 @@ using Newtonsoft.Json; {{#models}} {{#model}} -namespace {{package}} { +namespace {{packageName}}.Model { /// /// {{description}} diff --git a/samples/client/petstore/csharp/compile.bat b/samples/client/petstore/csharp/compile.bat index 63b79e03eed..bb6ae8097ea 100644 --- a/samples/client/petstore/csharp/compile.bat +++ b/samples/client/petstore/csharp/compile.bat @@ -1,3 +1,3 @@ SET CSCPATH=%SYSTEMROOT%\Microsoft.NET\Framework\v4.0.30319 -%CSCPATH%\csc /reference:bin/Newtonsoft.Json.dll;bin/RestSharp.dll /target:library /out:bin/IO.Swagger.Client.dll /recurse:src\*.cs /doc:bin/IO.Swagger.Client.xml +%CSCPATH%\csc /reference:bin/Newtonsoft.Json.dll;bin/RestSharp.dll /target:library /out:bin/.dll /recurse:src\*.cs /doc:bin/.xml diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs index 4e7975e3ad0..cf5162b62ea 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs @@ -4,7 +4,6 @@ using System.IO; using System.Linq; using System.Net; using System.Text; -using IO.Swagger.Client; namespace IO.Swagger.Client { /// From 6ab7be405834c17c3ac9a11ab06c5c43b6f7c9be Mon Sep 17 00:00:00 2001 From: wing328 Date: Thu, 18 Jun 2015 22:20:52 +0800 Subject: [PATCH 14/67] add package version --- .../src/main/resources/csharp/Configuration.mustache | 5 +++++ .../src/main/csharp/io/swagger/client/Configuration.cs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache b/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache index 86e35441493..485d97058ce 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/Configuration.mustache @@ -11,6 +11,11 @@ namespace {{packageName}}.Client { /// public class Configuration{ + /// + /// Version of the package + /// + public const string Version = "{{packageVersion}}"; + /// /// Gets or sets the API client. This is the default API client for making HTTP calls. /// diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs index cf5162b62ea..ab24fc1252c 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs @@ -11,6 +11,11 @@ namespace IO.Swagger.Client { /// public class Configuration{ + /// + /// Version of the package + /// + public const string Version = "1.0.0"; + /// /// Gets or sets the API client. This is the default API client for making HTTP calls. /// From 4ef34680cd53cb2b047bc2126a72f977001651fc Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Thu, 18 Jun 2015 10:30:53 -0700 Subject: [PATCH 15/67] renaming to ApiClient.mustache --- .../main/resources/php/{APIClient.mustache => ApiClient.mustache} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename modules/swagger-codegen/src/main/resources/php/{APIClient.mustache => ApiClient.mustache} (100%) diff --git a/modules/swagger-codegen/src/main/resources/php/APIClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache similarity index 100% rename from modules/swagger-codegen/src/main/resources/php/APIClient.mustache rename to modules/swagger-codegen/src/main/resources/php/ApiClient.mustache From d178d5e7d86a3c3d5e2c71e071a6adbf23e3e93b Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 19 Jun 2015 02:11:08 +0800 Subject: [PATCH 16/67] add sinatra template --- bin/silex-petstore-server.sh | 2 +- bin/sinatra-petstore-server.sh | 31 +++ .../languages/SinatraServerCodegen.java | 215 ++++++++++++++++ .../services/io.swagger.codegen.CodegenConfig | 1 + .../src/main/resources/sinatra/Gemfile | 4 + .../src/main/resources/sinatra/README.md | 29 +++ .../src/main/resources/sinatra/Swaggering.rb | 154 ++++++++++++ .../src/main/resources/sinatra/api.mustache | 57 +++++ .../src/main/resources/sinatra/config.ru | 2 + .../main/resources/sinatra/my_app.mustache | 12 + .../petstore/silex/SwaggerServer/.htaccess | 5 - .../petstore/silex/SwaggerServer/README.md | 10 - .../silex/SwaggerServer/composer.json | 5 - .../petstore/silex/SwaggerServer/index.php | 184 -------------- samples/client/petstore/silex/silex/.htaccess | 5 - samples/client/petstore/silex/silex/README.md | 10 - .../client/petstore/silex/silex/composer.json | 5 - samples/client/petstore/silex/silex/index.php | 184 -------------- samples/server/petstore/sinatra/Gemfile | 4 + samples/server/petstore/sinatra/README.md | 29 +++ .../server/petstore/sinatra/api/pet_api.rb | 231 ++++++++++++++++++ .../server/petstore/sinatra/api/store_api.rb | 103 ++++++++ .../server/petstore/sinatra/api/user_api.rb | 231 ++++++++++++++++++ samples/server/petstore/sinatra/config.rb | 2 + .../server/petstore/sinatra/lib/Swaggering.rb | 154 ++++++++++++ samples/server/petstore/sinatra/my_app.rb | 9 + 26 files changed, 1269 insertions(+), 409 deletions(-) create mode 100755 bin/sinatra-petstore-server.sh create mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SinatraServerCodegen.java create mode 100644 modules/swagger-codegen/src/main/resources/sinatra/Gemfile create mode 100644 modules/swagger-codegen/src/main/resources/sinatra/README.md create mode 100644 modules/swagger-codegen/src/main/resources/sinatra/Swaggering.rb create mode 100644 modules/swagger-codegen/src/main/resources/sinatra/api.mustache create mode 100644 modules/swagger-codegen/src/main/resources/sinatra/config.ru create mode 100644 modules/swagger-codegen/src/main/resources/sinatra/my_app.mustache delete mode 100644 samples/client/petstore/silex/SwaggerServer/.htaccess delete mode 100644 samples/client/petstore/silex/SwaggerServer/README.md delete mode 100644 samples/client/petstore/silex/SwaggerServer/composer.json delete mode 100644 samples/client/petstore/silex/SwaggerServer/index.php delete mode 100644 samples/client/petstore/silex/silex/.htaccess delete mode 100644 samples/client/petstore/silex/silex/README.md delete mode 100644 samples/client/petstore/silex/silex/composer.json delete mode 100644 samples/client/petstore/silex/silex/index.php create mode 100644 samples/server/petstore/sinatra/Gemfile create mode 100644 samples/server/petstore/sinatra/README.md create mode 100644 samples/server/petstore/sinatra/api/pet_api.rb create mode 100644 samples/server/petstore/sinatra/api/store_api.rb create mode 100644 samples/server/petstore/sinatra/api/user_api.rb create mode 100644 samples/server/petstore/sinatra/config.rb create mode 100644 samples/server/petstore/sinatra/lib/Swaggering.rb create mode 100644 samples/server/petstore/sinatra/my_app.rb diff --git a/bin/silex-petstore-server.sh b/bin/silex-petstore-server.sh index 5ead9db0002..ffa030b88c3 100755 --- a/bin/silex-petstore-server.sh +++ b/bin/silex-petstore-server.sh @@ -26,6 +26,6 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="$@ generate -t modules/swagger-codegen/src/main/resources/silex -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l silex -o samples/client/petstore/silex" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/silex -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l silex -o samples/server/petstore/silex" java $JAVA_OPTS -jar $executable $ags diff --git a/bin/sinatra-petstore-server.sh b/bin/sinatra-petstore-server.sh new file mode 100755 index 00000000000..4f7e19cee39 --- /dev/null +++ b/bin/sinatra-petstore-server.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +SCRIPT="$0" + +while [ -h "$SCRIPT" ] ; do + ls=`ls -ld "$SCRIPT"` + link=`expr "$ls" : '.*-> \(.*\)$'` + if expr "$link" : '/.*' > /dev/null; then + SCRIPT="$link" + else + SCRIPT=`dirname "$SCRIPT"`/"$link" + fi +done + +if [ ! -d "${APP_DIR}" ]; then + APP_DIR=`dirname "$SCRIPT"`/.. + APP_DIR=`cd "${APP_DIR}"; pwd` +fi + +executable="./modules/swagger-codegen-cli/target/swagger-codegen-cli.jar" + +if [ ! -f "$executable" ] +then + mvn clean package +fi + +# if you've executed sbt assembly previously it will use that instead. +export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" +ags="$@ generate -t modules/swagger-codegen/src/main/resources/sinatra -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l sinatra -o samples/server/petstore/sinatra" + +java $JAVA_OPTS -jar $executable $ags diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SinatraServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SinatraServerCodegen.java new file mode 100644 index 00000000000..318bf03130d --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SinatraServerCodegen.java @@ -0,0 +1,215 @@ +package io.swagger.codegen.languages; + +import io.swagger.codegen.CliOption; +import io.swagger.codegen.CodegenConfig; +import io.swagger.codegen.CodegenType; +import io.swagger.codegen.DefaultCodegen; +import io.swagger.codegen.SupportingFile; +import io.swagger.models.properties.ArrayProperty; +import io.swagger.models.properties.MapProperty; +import io.swagger.models.properties.Property; + +import java.io.File; +import java.util.Arrays; +import java.util.HashSet; + +public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfig { + protected String gemName = null; + protected String moduleName = null; + protected String gemVersion = "1.0.0"; + protected String libFolder = "lib"; + + public SinatraServerCodegen() { + super(); + apiPackage = "lib"; + outputFolder = "generated-code" + File.separator + "sinatra"; + + // no model + modelTemplateFiles.clear(); + apiTemplateFiles.put("api.mustache", ".rb"); + templateDir = "sinatra"; + + typeMapping.clear(); + languageSpecificPrimitives.clear(); + + reservedWords = new HashSet( + Arrays.asList( + "__FILE__", "and", "def", "end", "in", "or", "self", "unless", "__LINE__", + "begin", "defined?", "ensure", "module", "redo", "super", "until", "BEGIN", + "break", "do", "false", "next", "rescue", "then", "when", "END", "case", + "else", "for", "nil", "retry", "true", "while", "alias", "class", "elsif", + "if", "not", "return", "undef", "yield") + ); + + languageSpecificPrimitives.add("int"); + languageSpecificPrimitives.add("array"); + languageSpecificPrimitives.add("map"); + languageSpecificPrimitives.add("string"); + languageSpecificPrimitives.add("DateTime"); + + typeMapping.put("long", "int"); + typeMapping.put("integer", "int"); + typeMapping.put("Array", "array"); + typeMapping.put("String", "string"); + typeMapping.put("List", "array"); + typeMapping.put("map", "map"); + + // remove modelPackage and apiPackage added by default + cliOptions.clear(); + } + + @Override + public void processOpts() { + super.processOpts(); + + // use constant model/api package (folder path) + //setModelPackage("models"); + setApiPackage("api"); + + supportingFiles.add(new SupportingFile("my_app.mustache", "", "my_app.rb")); + supportingFiles.add(new SupportingFile("Swaggering.rb", libFolder, "Swaggering.rb")); + supportingFiles.add(new SupportingFile("config.ru", "", "config.rb")); + supportingFiles.add(new SupportingFile("Gemfile", "", "Gemfile")); + supportingFiles.add(new SupportingFile("README.md", "", "README.md")); + } + + public CodegenType getTag() { + return CodegenType.CLIENT; + } + + public String getName() { + return "sinatra"; + } + + public String getHelp() { + return "Generates a Sinatra server library."; + } + + @Override + public String escapeReservedWord(String name) { + return "_" + name; + } + + @Override + public String apiFileFolder() { + return outputFolder + File.separator + apiPackage.replace("/", File.separator); + } + + @Override + public String getTypeDeclaration(Property p) { + if (p instanceof ArrayProperty) { + ArrayProperty ap = (ArrayProperty) p; + Property inner = ap.getItems(); + return getSwaggerType(p) + "[" + getTypeDeclaration(inner) + "]"; + } else if (p instanceof MapProperty) { + MapProperty mp = (MapProperty) p; + Property inner = mp.getAdditionalProperties(); + return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]"; + } + return super.getTypeDeclaration(p); + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + String type = null; + if (typeMapping.containsKey(swaggerType)) { + type = typeMapping.get(swaggerType); + if (languageSpecificPrimitives.contains(type)) { + return type; + } + } else { + type = swaggerType; + } + if (type == null) { + return null; + } + return type; + } + + public String toDefaultValue(Property p) { + return "null"; + } + + @Override + public String toVarName(String name) { + // replace - with _ e.g. created-at => created_at + name = name.replaceAll("-", "_"); + + // if it's all uppper case, convert to lower case + if (name.matches("^[A-Z_]*$")) { + name = name.toLowerCase(); + } + + // camelize (lower first character) the variable name + // petId => pet_id + name = underscore(name); + + // for reserved word or word starting with number, append _ + if (reservedWords.contains(name) || name.matches("^\\d.*")) { + name = escapeReservedWord(name); + } + + return name; + } + + @Override + public String toParamName(String name) { + // should be the same as variable name + return toVarName(name); + } + + @Override + public String toModelName(String name) { + // model name cannot use reserved keyword, e.g. return + if (reservedWords.contains(name)) { + throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); + } + + // camelize the model name + // phone_number => PhoneNumber + return camelize(name); + } + + @Override + public String toModelFilename(String name) { + // model name cannot use reserved keyword, e.g. return + if (reservedWords.contains(name)) { + throw new RuntimeException(name + " (reserved word) cannot be used as a model name"); + } + + // underscore the model file name + // PhoneNumber.rb => phone_number.rb + return underscore(name); + } + + @Override + public String toApiFilename(String name) { + // replace - with _ e.g. created-at => created_at + name = name.replaceAll("-", "_"); + + // e.g. PhoneNumberApi.rb => phone_number_api.rb + return underscore(name) + "_api"; + } + + @Override + public String toApiName(String name) { + if (name.length() == 0) { + return "DefaultApi"; + } + // e.g. phone_number_api => PhoneNumberApi + return camelize(name) + "Api"; + } + + @Override + public String toOperationId(String operationId) { + // method name cannot use reserved keyword, e.g. return + if (reservedWords.contains(operationId)) { + throw new RuntimeException(operationId + " (reserved word) cannot be used as method name"); + } + + return underscore(operationId); + } + + +} diff --git a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig index ce3edfd1359..86cf9ef6013 100644 --- a/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig +++ b/modules/swagger-codegen/src/main/resources/META-INF/services/io.swagger.codegen.CodegenConfig @@ -15,6 +15,7 @@ io.swagger.codegen.languages.RubyClientCodegen io.swagger.codegen.languages.ScalaClientCodegen io.swagger.codegen.languages.ScalatraServerCodegen io.swagger.codegen.languages.SilexServerCodegen +io.swagger.codegen.languages.SinatraServerCodegen io.swagger.codegen.languages.SpringMVCServerCodegen io.swagger.codegen.languages.StaticDocCodegen io.swagger.codegen.languages.StaticHtmlGenerator diff --git a/modules/swagger-codegen/src/main/resources/sinatra/Gemfile b/modules/swagger-codegen/src/main/resources/sinatra/Gemfile new file mode 100644 index 00000000000..be9c3168ea6 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +gem "sinatra" +gem "sinatra-cross_origin" \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/sinatra/README.md b/modules/swagger-codegen/src/main/resources/sinatra/README.md new file mode 100644 index 00000000000..23c501353da --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/README.md @@ -0,0 +1,29 @@ +# Swagger for Sinatra + +## Overview +This is a project to provide Swagger support inside the [Sinatra](http://www.sinatrarb.com/) framework. You can find +out more about both the spec and the framework at http://swagger.wordnik.com. For more information about +Wordnik's APIs, please visit http://developer.wordnik.com. + +## Prerequisites +You need to install ruby 1.9.3 and the following gems: + +``` +sinatra +sinatra-cross_origin +``` + +## Getting started +This sample was generated with the [swagger-codegen](https://github.com/wordnik/swagger-codegen) project. + +``` +rackup -p 4567 config.ru +``` + +In your [swagger ui](https://github.com/wordnik/swagger-ui), put in the following URL: + +``` +http://localhost:4567/resources.json +``` + +Voila! diff --git a/modules/swagger-codegen/src/main/resources/sinatra/Swaggering.rb b/modules/swagger-codegen/src/main/resources/sinatra/Swaggering.rb new file mode 100644 index 00000000000..79aca1da2c9 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/Swaggering.rb @@ -0,0 +1,154 @@ +require 'json' +require 'sinatra/base' +require 'sinatra/cross_origin' + +class Configuration + attr_accessor :base_path, :api_version, :swagger_version, :format_specifier + + def initialize + @api_version = '1.0' + @base_path = 'http://localhost:4567' + @swagger_version = '1.1' + @format_specifier = ".json" + end +end + +class Swaggering < Sinatra::Base + register Sinatra::CrossOrigin + + @@routes = {} + @@configuration = Configuration.new + + attr_accessor :configuration + + def self.configure + get("/resources" + @@configuration.format_specifier) { + cross_origin + Swaggering.to_resource_listing + } + @@configuration ||= Configuration.new + yield(@@configuration) if block_given? + end + + def self.add_route(method, path, swag={}, opts={}, &block) + fullPath = swag["resourcePath"].to_s + @@configuration.format_specifier + path + + accepted = case method + when 'get' + get(fullPath, opts, &block) + true + when 'post' + post(fullPath, opts, &block) + true + when 'delete' + delete(fullPath, opts, &block) + true + when 'put' + put(fullPath, opts, &block) + true + else + false + end + + if accepted then + resourcePath = swag["resourcePath"].to_s + ops = @@routes[resourcePath] + if ops.nil? + ops = Array.new + @@routes.merge!(resourcePath => ops) + + get(resourcePath + @@configuration.format_specifier) do + cross_origin + Swaggering.to_api(resourcePath) + end + end + + swag.merge!("httpMethod" => method.to_s.upcase) + ops.push(swag) + end + end + + def self.to_resource_listing + apis = Array.new + (@@routes.keys).each do |key| + api = { + "path" => (key + ".{format}"), + "description" => "no description" + } + apis.push api + end + + resource = { + "apiVersion" => @@configuration.api_version, + "swaggerVersion" => @@configuration.swagger_version, + "apis" => apis + } + + resource.to_json + end + + def self.to_api(resourcePath) + apis = {} + models = [] + + @@routes[resourcePath].each do |route| + endpoint = route["endpoint"].gsub(/:(\w+)(\/?)/,'{\1}\2') + path = (resourcePath + ".{format}" + endpoint) + api = apis[path] + if api.nil? + api = {"path" => path, "description" => "description", "operations" => []} + apis.merge!(path => api) + end + + parameters = route["parameters"] + + unless parameters.nil? then + parameters.each do |param| + av_string = param["allowableValues"] + unless av_string.nil? + if av_string.count('[') > 0 + pattern = /^([A-Z]*)\[(.*)\]/ + match = pattern.match av_string + case match.to_a[1] + when "LIST" + allowables = match.to_a[2].split(',') + param["allowableValues"] = { + "valueType" => "LIST", + "values" => allowables + } + when "RANGE" + allowables = match.to_a[2].split(',') + param["allowableValues"] = { + "valueType" => "RANGE", + "min" => allowables[0], + "max" => allowables[1] + } + end + end + end + end + end + + op = { + "httpMethod" => route["httpMethod"], + "description" => route["summary"], + "responseClass" => route["responseClass"], + "notes" => route["notes"], + "nickname" => route["nickname"], + "summary" => route["summary"], + "parameters" => route["parameters"] + } + api["operations"].push(op) + end + + api_listing = { + "apiVersion" => @@configuration.api_version, + "swaggerVersion" => @@configuration.swagger_version, + "basePath" => @@configuration.base_path, + "resourcePath" => resourcePath, + "apis" => apis.values, + "models" => models + } + api_listing.to_json + end +end diff --git a/modules/swagger-codegen/src/main/resources/sinatra/api.mustache b/modules/swagger-codegen/src/main/resources/sinatra/api.mustache new file mode 100644 index 00000000000..cfeae19de7a --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/api.mustache @@ -0,0 +1,57 @@ +require 'json' + +{{#operations}} +{{#operation}} + +MyApp.add_route('{{httpMethod}}', '{{path}}', { + "resourcePath" => "/{{baseName}}", + "summary" => "{{{summary}}}", + "nickname" => "{{nickname}}", + "responseClass" => "{{#returnType}}{{returnType}}{{/returnType}}{{^returnType}}void{{/returnType}}", + "endpoint" => "{{path}}", + "notes" => "{{{notes}}}", + "parameters" => [ + {{#queryParams}} + { + "name" => "{{paramName}}", + "description" => "{{description}}", + "dataType" => "{{swaggerDataType}}", + "paramType" => "query", + "allowMultiple" => {{allowMultiple}}, + "allowableValues" => "{{allowableValues}}", + {{#defaultValue}}"defaultValue" => {{{defaultValue}}}{{/defaultValue}} + }, + {{/queryParams}} + {{#pathParams}} + { + "name" => "{{paramName}}", + "description" => "{{description}}", + "dataType" => "{{swaggerDataType}}", + "paramType" => "path", + }, + {{/pathParams}} + {{#headerParams}} + { + "name" => "{{paramName}}", + "description" => "{{description}}", + "dataType" => "{{swaggerDataType}}", + "paramType" => "header", + }, + {{/headerParams}} + {{#bodyParams}} + { + "name" => "body", + "description" => "{{description}}", + "dataType" => "{{swaggerDataType}}", + "paramType" => "body", + } + {{/bodyParams}} + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + +{{/operation}} +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/sinatra/config.ru b/modules/swagger-codegen/src/main/resources/sinatra/config.ru new file mode 100644 index 00000000000..395d0587123 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/config.ru @@ -0,0 +1,2 @@ +require './my_app' +run MyApp diff --git a/modules/swagger-codegen/src/main/resources/sinatra/my_app.mustache b/modules/swagger-codegen/src/main/resources/sinatra/my_app.mustache new file mode 100644 index 00000000000..72b5267a140 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/sinatra/my_app.mustache @@ -0,0 +1,12 @@ +require './lib/swaggering' + +# only need to extend if you want special configuration! +class MyApp < Swaggering + self.configure do |config| + config.api_version = '0.2' + end +end + +{{#apis}} +require './lib/{{className}}.rb' +{{/apis}} \ No newline at end of file diff --git a/samples/client/petstore/silex/SwaggerServer/.htaccess b/samples/client/petstore/silex/SwaggerServer/.htaccess deleted file mode 100644 index e47b5fb8a0c..00000000000 --- a/samples/client/petstore/silex/SwaggerServer/.htaccess +++ /dev/null @@ -1,5 +0,0 @@ - - RewriteEngine On - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L] - \ No newline at end of file diff --git a/samples/client/petstore/silex/SwaggerServer/README.md b/samples/client/petstore/silex/SwaggerServer/README.md deleted file mode 100644 index 9f35636b3f8..00000000000 --- a/samples/client/petstore/silex/SwaggerServer/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Swagger generated server - -## Overview -This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the -[swagger-spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. This -is an example of building a PHP server. - -This example uses the [Silex](http://silex.sensiolabs.org/) micro-framework. To see how to make this your own, please take a look at the template here: - -[TEMPLATES](https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/resources/silex/) diff --git a/samples/client/petstore/silex/SwaggerServer/composer.json b/samples/client/petstore/silex/SwaggerServer/composer.json deleted file mode 100644 index 466cd3fbc77..00000000000 --- a/samples/client/petstore/silex/SwaggerServer/composer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require": { - "silex/silex": "~1.2" - } -} \ No newline at end of file diff --git a/samples/client/petstore/silex/SwaggerServer/index.php b/samples/client/petstore/silex/SwaggerServer/index.php deleted file mode 100644 index 1526f3cb8f3..00000000000 --- a/samples/client/petstore/silex/SwaggerServer/index.php +++ /dev/null @@ -1,184 +0,0 @@ -POST('/user', function(Application $app, Request $request) { - - - return new Response('How about implementing createUser as a POST method ?'); - }); - - - -$app->POST('/user/createWithArray', function(Application $app, Request $request) { - - - return new Response('How about implementing createUsersWithArrayInput as a POST method ?'); - }); - - - -$app->POST('/user/createWithList', function(Application $app, Request $request) { - - - return new Response('How about implementing createUsersWithListInput as a POST method ?'); - }); - - - -$app->GET('/user/login', function(Application $app, Request $request) { - $username = $request->get('username'); $password = $request->get('password'); - - return new Response('How about implementing loginUser as a GET method ?'); - }); - - - -$app->GET('/user/logout', function(Application $app, Request $request) { - - - return new Response('How about implementing logoutUser as a GET method ?'); - }); - - - -$app->GET('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing getUserByName as a GET method ?'); - }); - - - -$app->PUT('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing updateUser as a PUT method ?'); - }); - - - -$app->DELETE('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing deleteUser as a DELETE method ?'); - }); - - - - - - - -$app->PUT('/pet', function(Application $app, Request $request) { - - - return new Response('How about implementing updatePet as a PUT method ?'); - }); - - - -$app->POST('/pet', function(Application $app, Request $request) { - - - return new Response('How about implementing addPet as a POST method ?'); - }); - - - -$app->GET('/pet/findByStatus', function(Application $app, Request $request) { - $status = $request->get('status'); - - return new Response('How about implementing findPetsByStatus as a GET method ?'); - }); - - - -$app->GET('/pet/findByTags', function(Application $app, Request $request) { - $tags = $request->get('tags'); - - return new Response('How about implementing findPetsByTags as a GET method ?'); - }); - - - -$app->GET('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - - return new Response('How about implementing getPetById as a GET method ?'); - }); - - - -$app->POST('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - $name = $request->get('name'); $status = $request->get('status'); - return new Response('How about implementing updatePetWithForm as a POST method ?'); - }); - - - -$app->DELETE('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - - return new Response('How about implementing deletePet as a DELETE method ?'); - }); - - - -$app->POST('/pet/{petId}/uploadImage', function(Application $app, Request $request, $pet_id) { - - $additional_metadata = $request->get('additional_metadata'); $file = $request->get('file'); - return new Response('How about implementing uploadFile as a POST method ?'); - }); - - - - - - - -$app->GET('/store/inventory', function(Application $app, Request $request) { - - - return new Response('How about implementing getInventory as a GET method ?'); - }); - - - -$app->POST('/store/order', function(Application $app, Request $request) { - - - return new Response('How about implementing placeOrder as a POST method ?'); - }); - - - -$app->GET('/store/order/{orderId}', function(Application $app, Request $request, $order_id) { - - - return new Response('How about implementing getOrderById as a GET method ?'); - }); - - - -$app->DELETE('/store/order/{orderId}', function(Application $app, Request $request, $order_id) { - - - return new Response('How about implementing deleteOrder as a DELETE method ?'); - }); - - - - - -$app->run(); diff --git a/samples/client/petstore/silex/silex/.htaccess b/samples/client/petstore/silex/silex/.htaccess deleted file mode 100644 index e47b5fb8a0c..00000000000 --- a/samples/client/petstore/silex/silex/.htaccess +++ /dev/null @@ -1,5 +0,0 @@ - - RewriteEngine On - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L] - \ No newline at end of file diff --git a/samples/client/petstore/silex/silex/README.md b/samples/client/petstore/silex/silex/README.md deleted file mode 100644 index 9f35636b3f8..00000000000 --- a/samples/client/petstore/silex/silex/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# Swagger generated server - -## Overview -This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the -[swagger-spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. This -is an example of building a PHP server. - -This example uses the [Silex](http://silex.sensiolabs.org/) micro-framework. To see how to make this your own, please take a look at the template here: - -[TEMPLATES](https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/resources/silex/) diff --git a/samples/client/petstore/silex/silex/composer.json b/samples/client/petstore/silex/silex/composer.json deleted file mode 100644 index 466cd3fbc77..00000000000 --- a/samples/client/petstore/silex/silex/composer.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "require": { - "silex/silex": "~1.2" - } -} \ No newline at end of file diff --git a/samples/client/petstore/silex/silex/index.php b/samples/client/petstore/silex/silex/index.php deleted file mode 100644 index 1526f3cb8f3..00000000000 --- a/samples/client/petstore/silex/silex/index.php +++ /dev/null @@ -1,184 +0,0 @@ -POST('/user', function(Application $app, Request $request) { - - - return new Response('How about implementing createUser as a POST method ?'); - }); - - - -$app->POST('/user/createWithArray', function(Application $app, Request $request) { - - - return new Response('How about implementing createUsersWithArrayInput as a POST method ?'); - }); - - - -$app->POST('/user/createWithList', function(Application $app, Request $request) { - - - return new Response('How about implementing createUsersWithListInput as a POST method ?'); - }); - - - -$app->GET('/user/login', function(Application $app, Request $request) { - $username = $request->get('username'); $password = $request->get('password'); - - return new Response('How about implementing loginUser as a GET method ?'); - }); - - - -$app->GET('/user/logout', function(Application $app, Request $request) { - - - return new Response('How about implementing logoutUser as a GET method ?'); - }); - - - -$app->GET('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing getUserByName as a GET method ?'); - }); - - - -$app->PUT('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing updateUser as a PUT method ?'); - }); - - - -$app->DELETE('/user/{username}', function(Application $app, Request $request, $username) { - - - return new Response('How about implementing deleteUser as a DELETE method ?'); - }); - - - - - - - -$app->PUT('/pet', function(Application $app, Request $request) { - - - return new Response('How about implementing updatePet as a PUT method ?'); - }); - - - -$app->POST('/pet', function(Application $app, Request $request) { - - - return new Response('How about implementing addPet as a POST method ?'); - }); - - - -$app->GET('/pet/findByStatus', function(Application $app, Request $request) { - $status = $request->get('status'); - - return new Response('How about implementing findPetsByStatus as a GET method ?'); - }); - - - -$app->GET('/pet/findByTags', function(Application $app, Request $request) { - $tags = $request->get('tags'); - - return new Response('How about implementing findPetsByTags as a GET method ?'); - }); - - - -$app->GET('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - - return new Response('How about implementing getPetById as a GET method ?'); - }); - - - -$app->POST('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - $name = $request->get('name'); $status = $request->get('status'); - return new Response('How about implementing updatePetWithForm as a POST method ?'); - }); - - - -$app->DELETE('/pet/{petId}', function(Application $app, Request $request, $pet_id) { - - - return new Response('How about implementing deletePet as a DELETE method ?'); - }); - - - -$app->POST('/pet/{petId}/uploadImage', function(Application $app, Request $request, $pet_id) { - - $additional_metadata = $request->get('additional_metadata'); $file = $request->get('file'); - return new Response('How about implementing uploadFile as a POST method ?'); - }); - - - - - - - -$app->GET('/store/inventory', function(Application $app, Request $request) { - - - return new Response('How about implementing getInventory as a GET method ?'); - }); - - - -$app->POST('/store/order', function(Application $app, Request $request) { - - - return new Response('How about implementing placeOrder as a POST method ?'); - }); - - - -$app->GET('/store/order/{orderId}', function(Application $app, Request $request, $order_id) { - - - return new Response('How about implementing getOrderById as a GET method ?'); - }); - - - -$app->DELETE('/store/order/{orderId}', function(Application $app, Request $request, $order_id) { - - - return new Response('How about implementing deleteOrder as a DELETE method ?'); - }); - - - - - -$app->run(); diff --git a/samples/server/petstore/sinatra/Gemfile b/samples/server/petstore/sinatra/Gemfile new file mode 100644 index 00000000000..be9c3168ea6 --- /dev/null +++ b/samples/server/petstore/sinatra/Gemfile @@ -0,0 +1,4 @@ +source 'https://rubygems.org' + +gem "sinatra" +gem "sinatra-cross_origin" \ No newline at end of file diff --git a/samples/server/petstore/sinatra/README.md b/samples/server/petstore/sinatra/README.md new file mode 100644 index 00000000000..23c501353da --- /dev/null +++ b/samples/server/petstore/sinatra/README.md @@ -0,0 +1,29 @@ +# Swagger for Sinatra + +## Overview +This is a project to provide Swagger support inside the [Sinatra](http://www.sinatrarb.com/) framework. You can find +out more about both the spec and the framework at http://swagger.wordnik.com. For more information about +Wordnik's APIs, please visit http://developer.wordnik.com. + +## Prerequisites +You need to install ruby 1.9.3 and the following gems: + +``` +sinatra +sinatra-cross_origin +``` + +## Getting started +This sample was generated with the [swagger-codegen](https://github.com/wordnik/swagger-codegen) project. + +``` +rackup -p 4567 config.ru +``` + +In your [swagger ui](https://github.com/wordnik/swagger-ui), put in the following URL: + +``` +http://localhost:4567/resources.json +``` + +Voila! diff --git a/samples/server/petstore/sinatra/api/pet_api.rb b/samples/server/petstore/sinatra/api/pet_api.rb new file mode 100644 index 00000000000..2fdc1f2a6e6 --- /dev/null +++ b/samples/server/petstore/sinatra/api/pet_api.rb @@ -0,0 +1,231 @@ +require 'json' + + +MyApp.add_route('PUT', '/pet', { + "resourcePath" => "/Pet", + "summary" => "Update an existing pet", + "nickname" => "update_pet", + "responseClass" => "void", + "endpoint" => "/pet", + "notes" => "", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "Pet object that needs to be added to the store", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/pet', { + "resourcePath" => "/Pet", + "summary" => "Add a new pet to the store", + "nickname" => "add_pet", + "responseClass" => "void", + "endpoint" => "/pet", + "notes" => "", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "Pet object that needs to be added to the store", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/pet/findByStatus', { + "resourcePath" => "/Pet", + "summary" => "Finds Pets by status", + "nickname" => "find_pets_by_status", + "responseClass" => "array[Pet]", + "endpoint" => "/pet/findByStatus", + "notes" => "Multiple status values can be provided with comma seperated strings", + "parameters" => [ + + { + "name" => "status", + "description" => "Status values that need to be considered for filter", + "dataType" => "", + "paramType" => "query", + "allowMultiple" => , + "allowableValues" => "", + "defaultValue" => available + }, + + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/pet/findByTags', { + "resourcePath" => "/Pet", + "summary" => "Finds Pets by tags", + "nickname" => "find_pets_by_tags", + "responseClass" => "array[Pet]", + "endpoint" => "/pet/findByTags", + "notes" => "Muliple tags can be provided with comma seperated strings. Use tag1, tag2, tag3 for testing.", + "parameters" => [ + + { + "name" => "tags", + "description" => "Tags to filter by", + "dataType" => "", + "paramType" => "query", + "allowMultiple" => , + "allowableValues" => "", + + }, + + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/pet/{petId}', { + "resourcePath" => "/Pet", + "summary" => "Find pet by ID", + "nickname" => "get_pet_by_id", + "responseClass" => "Pet", + "endpoint" => "/pet/{petId}", + "notes" => "Returns a pet when ID < 10. ID > 10 or nonintegers will simulate API error conditions", + "parameters" => [ + + + { + "name" => "pet_id", + "description" => "ID of pet that needs to be fetched", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/pet/{petId}', { + "resourcePath" => "/Pet", + "summary" => "Updates a pet in the store with form data", + "nickname" => "update_pet_with_form", + "responseClass" => "void", + "endpoint" => "/pet/{petId}", + "notes" => "", + "parameters" => [ + + + { + "name" => "pet_id", + "description" => "ID of pet that needs to be updated", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('DELETE', '/pet/{petId}', { + "resourcePath" => "/Pet", + "summary" => "Deletes a pet", + "nickname" => "delete_pet", + "responseClass" => "void", + "endpoint" => "/pet/{petId}", + "notes" => "", + "parameters" => [ + + + { + "name" => "pet_id", + "description" => "Pet id to delete", + "dataType" => "", + "paramType" => "path", + }, + + + { + "name" => "api_key", + "description" => "", + "dataType" => "", + "paramType" => "header", + }, + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/pet/{petId}/uploadImage', { + "resourcePath" => "/Pet", + "summary" => "uploads an image", + "nickname" => "upload_file", + "responseClass" => "void", + "endpoint" => "/pet/{petId}/uploadImage", + "notes" => "", + "parameters" => [ + + + { + "name" => "pet_id", + "description" => "ID of pet to update", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + diff --git a/samples/server/petstore/sinatra/api/store_api.rb b/samples/server/petstore/sinatra/api/store_api.rb new file mode 100644 index 00000000000..245ae23bff7 --- /dev/null +++ b/samples/server/petstore/sinatra/api/store_api.rb @@ -0,0 +1,103 @@ +require 'json' + + +MyApp.add_route('GET', '/store/inventory', { + "resourcePath" => "/Store", + "summary" => "Returns pet inventories by status", + "nickname" => "get_inventory", + "responseClass" => "map[string,int]", + "endpoint" => "/store/inventory", + "notes" => "Returns a map of status codes to quantities", + "parameters" => [ + + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/store/order', { + "resourcePath" => "/Store", + "summary" => "Place an order for a pet", + "nickname" => "place_order", + "responseClass" => "Order", + "endpoint" => "/store/order", + "notes" => "", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "order placed for purchasing the pet", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/store/order/{orderId}', { + "resourcePath" => "/Store", + "summary" => "Find purchase order by ID", + "nickname" => "get_order_by_id", + "responseClass" => "Order", + "endpoint" => "/store/order/{orderId}", + "notes" => "For valid response try integer IDs with value <= 5 or > 10. Other values will generated exceptions", + "parameters" => [ + + + { + "name" => "order_id", + "description" => "ID of pet that needs to be fetched", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('DELETE', '/store/order/{orderId}', { + "resourcePath" => "/Store", + "summary" => "Delete purchase order by ID", + "nickname" => "delete_order", + "responseClass" => "void", + "endpoint" => "/store/order/{orderId}", + "notes" => "For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors", + "parameters" => [ + + + { + "name" => "order_id", + "description" => "ID of the order that needs to be deleted", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + diff --git a/samples/server/petstore/sinatra/api/user_api.rb b/samples/server/petstore/sinatra/api/user_api.rb new file mode 100644 index 00000000000..8cbd49d72a0 --- /dev/null +++ b/samples/server/petstore/sinatra/api/user_api.rb @@ -0,0 +1,231 @@ +require 'json' + + +MyApp.add_route('POST', '/user', { + "resourcePath" => "/User", + "summary" => "Create user", + "nickname" => "create_user", + "responseClass" => "void", + "endpoint" => "/user", + "notes" => "This can only be done by the logged in user.", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "Created user object", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/user/createWithArray', { + "resourcePath" => "/User", + "summary" => "Creates list of users with given input array", + "nickname" => "create_users_with_array_input", + "responseClass" => "void", + "endpoint" => "/user/createWithArray", + "notes" => "", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "List of user object", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('POST', '/user/createWithList', { + "resourcePath" => "/User", + "summary" => "Creates list of users with given input array", + "nickname" => "create_users_with_list_input", + "responseClass" => "void", + "endpoint" => "/user/createWithList", + "notes" => "", + "parameters" => [ + + + + + { + "name" => "body", + "description" => "List of user object", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/user/login', { + "resourcePath" => "/User", + "summary" => "Logs user into the system", + "nickname" => "login_user", + "responseClass" => "string", + "endpoint" => "/user/login", + "notes" => "", + "parameters" => [ + + { + "name" => "username", + "description" => "The user name for login", + "dataType" => "", + "paramType" => "query", + "allowMultiple" => , + "allowableValues" => "", + + }, + + { + "name" => "password", + "description" => "The password for login in clear text", + "dataType" => "", + "paramType" => "query", + "allowMultiple" => , + "allowableValues" => "", + + }, + + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/user/logout', { + "resourcePath" => "/User", + "summary" => "Logs out current logged in user session", + "nickname" => "logout_user", + "responseClass" => "void", + "endpoint" => "/user/logout", + "notes" => "", + "parameters" => [ + + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('GET', '/user/{username}', { + "resourcePath" => "/User", + "summary" => "Get user by user name", + "nickname" => "get_user_by_name", + "responseClass" => "User", + "endpoint" => "/user/{username}", + "notes" => "", + "parameters" => [ + + + { + "name" => "username", + "description" => "The name that needs to be fetched. Use user1 for testing. ", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('PUT', '/user/{username}', { + "resourcePath" => "/User", + "summary" => "Updated user", + "nickname" => "update_user", + "responseClass" => "void", + "endpoint" => "/user/{username}", + "notes" => "This can only be done by the logged in user.", + "parameters" => [ + + + { + "name" => "username", + "description" => "name that need to be deleted", + "dataType" => "", + "paramType" => "path", + }, + + + + { + "name" => "body", + "description" => "Updated user object", + "dataType" => "", + "paramType" => "body", + } + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + + +MyApp.add_route('DELETE', '/user/{username}', { + "resourcePath" => "/User", + "summary" => "Delete user", + "nickname" => "delete_user", + "responseClass" => "void", + "endpoint" => "/user/{username}", + "notes" => "This can only be done by the logged in user.", + "parameters" => [ + + + { + "name" => "username", + "description" => "The name that needs to be deleted", + "dataType" => "", + "paramType" => "path", + }, + + + + ]}) do + cross_origin + # the guts live here + + {"message" => "yes, it worked"}.to_json +end + diff --git a/samples/server/petstore/sinatra/config.rb b/samples/server/petstore/sinatra/config.rb new file mode 100644 index 00000000000..395d0587123 --- /dev/null +++ b/samples/server/petstore/sinatra/config.rb @@ -0,0 +1,2 @@ +require './my_app' +run MyApp diff --git a/samples/server/petstore/sinatra/lib/Swaggering.rb b/samples/server/petstore/sinatra/lib/Swaggering.rb new file mode 100644 index 00000000000..79aca1da2c9 --- /dev/null +++ b/samples/server/petstore/sinatra/lib/Swaggering.rb @@ -0,0 +1,154 @@ +require 'json' +require 'sinatra/base' +require 'sinatra/cross_origin' + +class Configuration + attr_accessor :base_path, :api_version, :swagger_version, :format_specifier + + def initialize + @api_version = '1.0' + @base_path = 'http://localhost:4567' + @swagger_version = '1.1' + @format_specifier = ".json" + end +end + +class Swaggering < Sinatra::Base + register Sinatra::CrossOrigin + + @@routes = {} + @@configuration = Configuration.new + + attr_accessor :configuration + + def self.configure + get("/resources" + @@configuration.format_specifier) { + cross_origin + Swaggering.to_resource_listing + } + @@configuration ||= Configuration.new + yield(@@configuration) if block_given? + end + + def self.add_route(method, path, swag={}, opts={}, &block) + fullPath = swag["resourcePath"].to_s + @@configuration.format_specifier + path + + accepted = case method + when 'get' + get(fullPath, opts, &block) + true + when 'post' + post(fullPath, opts, &block) + true + when 'delete' + delete(fullPath, opts, &block) + true + when 'put' + put(fullPath, opts, &block) + true + else + false + end + + if accepted then + resourcePath = swag["resourcePath"].to_s + ops = @@routes[resourcePath] + if ops.nil? + ops = Array.new + @@routes.merge!(resourcePath => ops) + + get(resourcePath + @@configuration.format_specifier) do + cross_origin + Swaggering.to_api(resourcePath) + end + end + + swag.merge!("httpMethod" => method.to_s.upcase) + ops.push(swag) + end + end + + def self.to_resource_listing + apis = Array.new + (@@routes.keys).each do |key| + api = { + "path" => (key + ".{format}"), + "description" => "no description" + } + apis.push api + end + + resource = { + "apiVersion" => @@configuration.api_version, + "swaggerVersion" => @@configuration.swagger_version, + "apis" => apis + } + + resource.to_json + end + + def self.to_api(resourcePath) + apis = {} + models = [] + + @@routes[resourcePath].each do |route| + endpoint = route["endpoint"].gsub(/:(\w+)(\/?)/,'{\1}\2') + path = (resourcePath + ".{format}" + endpoint) + api = apis[path] + if api.nil? + api = {"path" => path, "description" => "description", "operations" => []} + apis.merge!(path => api) + end + + parameters = route["parameters"] + + unless parameters.nil? then + parameters.each do |param| + av_string = param["allowableValues"] + unless av_string.nil? + if av_string.count('[') > 0 + pattern = /^([A-Z]*)\[(.*)\]/ + match = pattern.match av_string + case match.to_a[1] + when "LIST" + allowables = match.to_a[2].split(',') + param["allowableValues"] = { + "valueType" => "LIST", + "values" => allowables + } + when "RANGE" + allowables = match.to_a[2].split(',') + param["allowableValues"] = { + "valueType" => "RANGE", + "min" => allowables[0], + "max" => allowables[1] + } + end + end + end + end + end + + op = { + "httpMethod" => route["httpMethod"], + "description" => route["summary"], + "responseClass" => route["responseClass"], + "notes" => route["notes"], + "nickname" => route["nickname"], + "summary" => route["summary"], + "parameters" => route["parameters"] + } + api["operations"].push(op) + end + + api_listing = { + "apiVersion" => @@configuration.api_version, + "swaggerVersion" => @@configuration.swagger_version, + "basePath" => @@configuration.base_path, + "resourcePath" => resourcePath, + "apis" => apis.values, + "models" => models + } + api_listing.to_json + end +end diff --git a/samples/server/petstore/sinatra/my_app.rb b/samples/server/petstore/sinatra/my_app.rb new file mode 100644 index 00000000000..4e692eb53bc --- /dev/null +++ b/samples/server/petstore/sinatra/my_app.rb @@ -0,0 +1,9 @@ +require './lib/swaggering' + +# only need to extend if you want special configuration! +class MyApp < Swaggering + self.configure do |config| + config.api_version = '0.2' + end +end + From 0b0325b8afd49d29594da6c6a5384153c71fe9e8 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 19 Jun 2015 02:32:50 +0800 Subject: [PATCH 17/67] update readme, fix swaggering name --- .../languages/SinatraServerCodegen.java | 4 ++-- .../src/main/resources/sinatra/README.md | 6 +++--- samples/server/petstore/sinatra/Gemfile.lock | 19 +++++++++++++++++++ samples/server/petstore/sinatra/README.md | 6 +++--- .../petstore/sinatra/{config.rb => config.ru} | 0 .../lib/{Swaggering.rb => swaggering.rb} | 0 6 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 samples/server/petstore/sinatra/Gemfile.lock rename samples/server/petstore/sinatra/{config.rb => config.ru} (100%) rename samples/server/petstore/sinatra/lib/{Swaggering.rb => swaggering.rb} (100%) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SinatraServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SinatraServerCodegen.java index 318bf03130d..44cf978eb1d 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SinatraServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/SinatraServerCodegen.java @@ -67,8 +67,8 @@ public class SinatraServerCodegen extends DefaultCodegen implements CodegenConfi setApiPackage("api"); supportingFiles.add(new SupportingFile("my_app.mustache", "", "my_app.rb")); - supportingFiles.add(new SupportingFile("Swaggering.rb", libFolder, "Swaggering.rb")); - supportingFiles.add(new SupportingFile("config.ru", "", "config.rb")); + supportingFiles.add(new SupportingFile("Swaggering.rb", libFolder, "swaggering.rb")); + supportingFiles.add(new SupportingFile("config.ru", "", "config.ru")); supportingFiles.add(new SupportingFile("Gemfile", "", "Gemfile")); supportingFiles.add(new SupportingFile("README.md", "", "README.md")); } diff --git a/modules/swagger-codegen/src/main/resources/sinatra/README.md b/modules/swagger-codegen/src/main/resources/sinatra/README.md index 23c501353da..c5b8cfffe77 100644 --- a/modules/swagger-codegen/src/main/resources/sinatra/README.md +++ b/modules/swagger-codegen/src/main/resources/sinatra/README.md @@ -2,7 +2,7 @@ ## Overview This is a project to provide Swagger support inside the [Sinatra](http://www.sinatrarb.com/) framework. You can find -out more about both the spec and the framework at http://swagger.wordnik.com. For more information about +out more about both the spec and the framework at http://swagger.io. For more information about Wordnik's APIs, please visit http://developer.wordnik.com. ## Prerequisites @@ -14,13 +14,13 @@ sinatra-cross_origin ``` ## Getting started -This sample was generated with the [swagger-codegen](https://github.com/wordnik/swagger-codegen) project. +This sample was generated with the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. ``` rackup -p 4567 config.ru ``` -In your [swagger ui](https://github.com/wordnik/swagger-ui), put in the following URL: +In your [swagger ui](https://github.com/swagger-api/swagger-ui), put in the following URL: ``` http://localhost:4567/resources.json diff --git a/samples/server/petstore/sinatra/Gemfile.lock b/samples/server/petstore/sinatra/Gemfile.lock new file mode 100644 index 00000000000..3b7c05b4083 --- /dev/null +++ b/samples/server/petstore/sinatra/Gemfile.lock @@ -0,0 +1,19 @@ +GEM + remote: https://rubygems.org/ + specs: + rack (1.6.4) + rack-protection (1.5.3) + rack + sinatra (1.4.6) + rack (~> 1.4) + rack-protection (~> 1.4) + tilt (>= 1.3, < 3) + sinatra-cross_origin (0.3.2) + tilt (2.0.1) + +PLATFORMS + ruby + +DEPENDENCIES + sinatra + sinatra-cross_origin diff --git a/samples/server/petstore/sinatra/README.md b/samples/server/petstore/sinatra/README.md index 23c501353da..c5b8cfffe77 100644 --- a/samples/server/petstore/sinatra/README.md +++ b/samples/server/petstore/sinatra/README.md @@ -2,7 +2,7 @@ ## Overview This is a project to provide Swagger support inside the [Sinatra](http://www.sinatrarb.com/) framework. You can find -out more about both the spec and the framework at http://swagger.wordnik.com. For more information about +out more about both the spec and the framework at http://swagger.io. For more information about Wordnik's APIs, please visit http://developer.wordnik.com. ## Prerequisites @@ -14,13 +14,13 @@ sinatra-cross_origin ``` ## Getting started -This sample was generated with the [swagger-codegen](https://github.com/wordnik/swagger-codegen) project. +This sample was generated with the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. ``` rackup -p 4567 config.ru ``` -In your [swagger ui](https://github.com/wordnik/swagger-ui), put in the following URL: +In your [swagger ui](https://github.com/swagger-api/swagger-ui), put in the following URL: ``` http://localhost:4567/resources.json diff --git a/samples/server/petstore/sinatra/config.rb b/samples/server/petstore/sinatra/config.ru similarity index 100% rename from samples/server/petstore/sinatra/config.rb rename to samples/server/petstore/sinatra/config.ru diff --git a/samples/server/petstore/sinatra/lib/Swaggering.rb b/samples/server/petstore/sinatra/lib/swaggering.rb similarity index 100% rename from samples/server/petstore/sinatra/lib/Swaggering.rb rename to samples/server/petstore/sinatra/lib/swaggering.rb From f9574715096b741d79f13b161e5a5d7b15d86b5b Mon Sep 17 00:00:00 2001 From: William Cheng Date: Fri, 19 Jun 2015 02:37:08 +0800 Subject: [PATCH 18/67] update silex sample code location --- .../petstore/silex/SwaggerServer/.htaccess | 5 + .../petstore/silex/SwaggerServer/README.md | 10 + .../silex/SwaggerServer/composer.json | 5 + .../petstore/silex/SwaggerServer/index.php | 184 ++++++++++++++++++ 4 files changed, 204 insertions(+) create mode 100644 samples/server/petstore/silex/SwaggerServer/.htaccess create mode 100644 samples/server/petstore/silex/SwaggerServer/README.md create mode 100644 samples/server/petstore/silex/SwaggerServer/composer.json create mode 100644 samples/server/petstore/silex/SwaggerServer/index.php diff --git a/samples/server/petstore/silex/SwaggerServer/.htaccess b/samples/server/petstore/silex/SwaggerServer/.htaccess new file mode 100644 index 00000000000..e47b5fb8a0c --- /dev/null +++ b/samples/server/petstore/silex/SwaggerServer/.htaccess @@ -0,0 +1,5 @@ + + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L] + \ No newline at end of file diff --git a/samples/server/petstore/silex/SwaggerServer/README.md b/samples/server/petstore/silex/SwaggerServer/README.md new file mode 100644 index 00000000000..9f35636b3f8 --- /dev/null +++ b/samples/server/petstore/silex/SwaggerServer/README.md @@ -0,0 +1,10 @@ +# Swagger generated server + +## Overview +This server was generated by the [swagger-codegen](https://github.com/swagger-api/swagger-codegen) project. By using the +[swagger-spec](https://github.com/swagger-api/swagger-core/wiki) from a remote server, you can easily generate a server stub. This +is an example of building a PHP server. + +This example uses the [Silex](http://silex.sensiolabs.org/) micro-framework. To see how to make this your own, please take a look at the template here: + +[TEMPLATES](https://github.com/swagger-api/swagger-codegen/tree/master/modules/swagger-codegen/src/main/resources/silex/) diff --git a/samples/server/petstore/silex/SwaggerServer/composer.json b/samples/server/petstore/silex/SwaggerServer/composer.json new file mode 100644 index 00000000000..466cd3fbc77 --- /dev/null +++ b/samples/server/petstore/silex/SwaggerServer/composer.json @@ -0,0 +1,5 @@ +{ + "require": { + "silex/silex": "~1.2" + } +} \ No newline at end of file diff --git a/samples/server/petstore/silex/SwaggerServer/index.php b/samples/server/petstore/silex/SwaggerServer/index.php new file mode 100644 index 00000000000..1526f3cb8f3 --- /dev/null +++ b/samples/server/petstore/silex/SwaggerServer/index.php @@ -0,0 +1,184 @@ +POST('/user', function(Application $app, Request $request) { + + + return new Response('How about implementing createUser as a POST method ?'); + }); + + + +$app->POST('/user/createWithArray', function(Application $app, Request $request) { + + + return new Response('How about implementing createUsersWithArrayInput as a POST method ?'); + }); + + + +$app->POST('/user/createWithList', function(Application $app, Request $request) { + + + return new Response('How about implementing createUsersWithListInput as a POST method ?'); + }); + + + +$app->GET('/user/login', function(Application $app, Request $request) { + $username = $request->get('username'); $password = $request->get('password'); + + return new Response('How about implementing loginUser as a GET method ?'); + }); + + + +$app->GET('/user/logout', function(Application $app, Request $request) { + + + return new Response('How about implementing logoutUser as a GET method ?'); + }); + + + +$app->GET('/user/{username}', function(Application $app, Request $request, $username) { + + + return new Response('How about implementing getUserByName as a GET method ?'); + }); + + + +$app->PUT('/user/{username}', function(Application $app, Request $request, $username) { + + + return new Response('How about implementing updateUser as a PUT method ?'); + }); + + + +$app->DELETE('/user/{username}', function(Application $app, Request $request, $username) { + + + return new Response('How about implementing deleteUser as a DELETE method ?'); + }); + + + + + + + +$app->PUT('/pet', function(Application $app, Request $request) { + + + return new Response('How about implementing updatePet as a PUT method ?'); + }); + + + +$app->POST('/pet', function(Application $app, Request $request) { + + + return new Response('How about implementing addPet as a POST method ?'); + }); + + + +$app->GET('/pet/findByStatus', function(Application $app, Request $request) { + $status = $request->get('status'); + + return new Response('How about implementing findPetsByStatus as a GET method ?'); + }); + + + +$app->GET('/pet/findByTags', function(Application $app, Request $request) { + $tags = $request->get('tags'); + + return new Response('How about implementing findPetsByTags as a GET method ?'); + }); + + + +$app->GET('/pet/{petId}', function(Application $app, Request $request, $pet_id) { + + + return new Response('How about implementing getPetById as a GET method ?'); + }); + + + +$app->POST('/pet/{petId}', function(Application $app, Request $request, $pet_id) { + + $name = $request->get('name'); $status = $request->get('status'); + return new Response('How about implementing updatePetWithForm as a POST method ?'); + }); + + + +$app->DELETE('/pet/{petId}', function(Application $app, Request $request, $pet_id) { + + + return new Response('How about implementing deletePet as a DELETE method ?'); + }); + + + +$app->POST('/pet/{petId}/uploadImage', function(Application $app, Request $request, $pet_id) { + + $additional_metadata = $request->get('additional_metadata'); $file = $request->get('file'); + return new Response('How about implementing uploadFile as a POST method ?'); + }); + + + + + + + +$app->GET('/store/inventory', function(Application $app, Request $request) { + + + return new Response('How about implementing getInventory as a GET method ?'); + }); + + + +$app->POST('/store/order', function(Application $app, Request $request) { + + + return new Response('How about implementing placeOrder as a POST method ?'); + }); + + + +$app->GET('/store/order/{orderId}', function(Application $app, Request $request, $order_id) { + + + return new Response('How about implementing getOrderById as a GET method ?'); + }); + + + +$app->DELETE('/store/order/{orderId}', function(Application $app, Request $request, $order_id) { + + + return new Response('How about implementing deleteOrder as a DELETE method ?'); + }); + + + + + +$app->run(); From 1aeb50feefe1de90be296332f927ce0da962f5f0 Mon Sep 17 00:00:00 2001 From: Andrew B Date: Thu, 18 Jun 2015 14:41:17 -0700 Subject: [PATCH 19/67] Replacing getClientResponseStatus() with getStatusInfo() --- .../src/main/resources/Java/ApiClient.mustache | 6 +++--- .../java/src/main/java/io/swagger/client/ApiClient.java | 6 +++--- .../java/src/main/java/io/swagger/client/api/PetApi.java | 2 +- .../java/src/main/java/io/swagger/client/model/Pet.java | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache index 352401ba0d8..e12c835a90a 100644 --- a/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/Java/ApiClient.mustache @@ -421,10 +421,10 @@ public class ApiClient { throw new ApiException(500, "unknown method type " + method); } - if(response.getClientResponseStatus() == ClientResponse.Status.NO_CONTENT) { + if(response.getStatusInfo() == ClientResponse.Status.NO_CONTENT) { return null; } - else if(response.getClientResponseStatus().getFamily() == Family.SUCCESSFUL) { + else if(response.getStatusInfo().getFamily() == Family.SUCCESSFUL) { if(response.hasEntity()) { return (String) response.getEntity(String.class); } @@ -445,7 +445,7 @@ public class ApiClient { } } throw new ApiException( - response.getClientResponseStatus().getStatusCode(), + response.getStatusInfo().getStatusCode(), message, response.getHeaders(), respBody); diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java index 0adcbe7031d..a95f5f7a960 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/ApiClient.java @@ -420,10 +420,10 @@ public class ApiClient { throw new ApiException(500, "unknown method type " + method); } - if(response.getClientResponseStatus() == ClientResponse.Status.NO_CONTENT) { + if(response.getStatusInfo() == ClientResponse.Status.NO_CONTENT) { return null; } - else if(response.getClientResponseStatus().getFamily() == Family.SUCCESSFUL) { + else if(response.getStatusInfo().getFamily() == Family.SUCCESSFUL) { if(response.hasEntity()) { return (String) response.getEntity(String.class); } @@ -444,7 +444,7 @@ public class ApiClient { } } throw new ApiException( - response.getClientResponseStatus().getStatusCode(), + response.getStatusInfo().getStatusCode(), message, response.getHeaders(), respBody); diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java b/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java index c102cf00b51..bc793fd41ee 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/api/PetApi.java @@ -322,7 +322,7 @@ public class PetApi { } try { - String[] authNames = new String[] { "petstore_auth", "api_key" }; + String[] authNames = new String[] { "api_key", "petstore_auth" }; String response = apiClient.invokeAPI(path, "GET", queryParams, postBody, headerParams, formParams, accept, contentType, authNames); if(response != null){ return (Pet) apiClient.deserialize(response, "", Pet.class); diff --git a/samples/client/petstore/java/src/main/java/io/swagger/client/model/Pet.java b/samples/client/petstore/java/src/main/java/io/swagger/client/model/Pet.java index ddd0e1038c0..cf7ace02309 100644 --- a/samples/client/petstore/java/src/main/java/io/swagger/client/model/Pet.java +++ b/samples/client/petstore/java/src/main/java/io/swagger/client/model/Pet.java @@ -1,8 +1,8 @@ package io.swagger.client.model; import io.swagger.client.model.Category; -import java.util.*; import io.swagger.client.model.Tag; +import java.util.*; import io.swagger.annotations.*; import com.fasterxml.jackson.annotation.JsonProperty; From 4495774fd5b0b59ea4e5d98e28482a47499b8a06 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Thu, 18 Jun 2015 15:08:45 -0700 Subject: [PATCH 20/67] proper autoloader and move generated files to PSR-4 compliant locations --- .../codegen/languages/PhpClientCodegen.java | 95 ++++++++++++++++--- .../src/main/resources/php/autoload.mustache | 29 ++++++ .../src/main/resources/php/require.mustache | 13 --- 3 files changed, 113 insertions(+), 24 deletions(-) create mode 100644 modules/swagger-codegen/src/main/resources/php/autoload.mustache delete mode 100644 modules/swagger-codegen/src/main/resources/php/require.mustache diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 10c03fe4381..af4867108a8 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -1,5 +1,6 @@ package io.swagger.codegen.languages; +import io.swagger.codegen.CliOption; import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenType; import io.swagger.codegen.DefaultCodegen; @@ -12,22 +13,25 @@ import java.io.File; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.Map; public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { protected String invokerPackage = "io.swagger.client"; protected String groupId = "io.swagger"; protected String artifactId = "swagger-client"; protected String artifactVersion = "1.0.0"; + protected String rootNamespace; + protected String invokerNamespace; + protected String modelNamespace; + protected String apiNamespace; public PhpClientCodegen() { super(); - invokerPackage = camelize("SwaggerClient"); - - String packagePath = invokerPackage + "-php"; - - modelPackage = packagePath + "/lib/models"; - apiPackage = packagePath + "/lib"; + rootNamespace = "Swagger"; + invokerPackage = "Client"; + modelPackage = "Models"; + apiPackage = "Api"; outputFolder = "generated-code/php"; modelTemplateFiles.put("model.mustache", ".php"); apiTemplateFiles.put("api.mustache", ".php"); @@ -78,11 +82,8 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("list", "array"); typeMapping.put("object", "object"); - supportingFiles.add(new SupportingFile("composer.mustache", packagePath.replace('/', File.separatorChar), "composer.json")); - supportingFiles.add(new SupportingFile("configuration.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "Configuration.php")); - supportingFiles.add(new SupportingFile("ApiClient.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "ApiClient.php")); - supportingFiles.add(new SupportingFile("ApiException.mustache", (packagePath + "/lib").replace('/', File.separatorChar), "ApiException.php")); - supportingFiles.add(new SupportingFile("require.mustache", packagePath.replace('/', File.separatorChar), invokerPackage + ".php")); + cliOptions.add(new CliOption("rootNamespace", "root namespace from which other namespaces derive")); + cliOptions.add(new CliOption("invokerPackage", "namespace for core, non-api-specific classes")); } public CodegenType getTag() { @@ -97,6 +98,38 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { return "Generates a PHP client library."; } + @Override + public void processOpts() { + super.processOpts(); + + if (additionalProperties.containsKey("invokerPackage")) { + this.setInvokerPackage((String) additionalProperties.get("invokerPackage")); + } + + if (additionalProperties.containsKey("rootNamespace")) { + this.setRootNamespace((String) additionalProperties.get("rootNamespace")); + } + + setNamespacesFromPackages(); + prefixPackages(); + + supportingFiles.add(new SupportingFile("configuration.mustache", invokerPackage.replace('/', File.separatorChar), "Configuration.php")); + supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerPackage.replace('/', File.separatorChar), "ApiClient.php")); + supportingFiles.add(new SupportingFile("ApiException.mustache", invokerPackage.replace('/', File.separatorChar), "ApiException.php")); + supportingFiles.add(new SupportingFile("composer.mustache", "", "composer.json")); + supportingFiles.add(new SupportingFile("autoload.mustache", "", "autoload.php")); + } + + protected String getSrcDir(String packageName) { + return rootNamespace + "/src/" + packageName; + } + + protected void prefixPackages() { + setApiPackage(getSrcDir(apiPackage)); + setInvokerPackage(getSrcDir(invokerPackage)); + setModelPackage(getSrcDir(modelPackage)); + } + @Override public String escapeReservedWord(String name) { return "_" + name; @@ -149,6 +182,13 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { return "null"; } + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } + + public void setRootNamespace(String rootNamespace) { + this.rootNamespace = rootNamespace; + } @Override public String toVarName(String name) { @@ -187,4 +227,37 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { return toModelName(name); } + public String toNamespace(String packageName) { + return rootNamespace + "\\" + packageName.replace('/', '\\').replace('.', '\\'); + } + + protected void setNamespacesFromPackages() { + invokerNamespace = toNamespace(invokerPackage); + apiNamespace = toNamespace(apiPackage); + modelNamespace = toNamespace(modelPackage); + } + + @Override + public Map postProcessModels(Map objs) { + return addNamespaces(super.postProcessModels(objs)); + } + + @Override + public Map postProcessOperations(Map objs) { + return addNamespaces(super.postProcessOperations(objs)); + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + return addNamespaces(super.postProcessSupportingFileData(objs)); + } + + protected Map addNamespaces(Map objs) { + objs.put("rootNamespace", rootNamespace); + objs.put("invokerNamespace", invokerNamespace); + objs.put("apiNamespace", apiNamespace); + objs.put("modelNamespace", modelNamespace); + + return objs; + } } diff --git a/modules/swagger-codegen/src/main/resources/php/autoload.mustache b/modules/swagger-codegen/src/main/resources/php/autoload.mustache new file mode 100644 index 00000000000..5ed11c11041 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php/autoload.mustache @@ -0,0 +1,29 @@ + From bb113229194935651573c48030d1dec94c1e7c62 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Thu, 18 Jun 2015 15:41:12 -0700 Subject: [PATCH 21/67] use proper namespaces, getters/setters, and phpdocs --- .../src/main/resources/php/ApiClient.mustache | 2 +- .../main/resources/php/ApiException.mustache | 2 +- .../src/main/resources/php/api.mustache | 10 +++-- .../src/main/resources/php/autoload.mustache | 40 +++++++++---------- .../main/resources/php/configuration.mustache | 2 +- .../src/main/resources/php/model.mustache | 31 ++++++++++---- 6 files changed, 54 insertions(+), 33 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index 6356143f914..564bc1ddd66 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -15,7 +15,7 @@ * limitations under the License. */ -namespace {{invokerPackage}}; +namespace {{invokerNamespace}}; class ApiClient { diff --git a/modules/swagger-codegen/src/main/resources/php/ApiException.mustache b/modules/swagger-codegen/src/main/resources/php/ApiException.mustache index b66c3a51eb7..096979c11cb 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiException.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiException.mustache @@ -15,7 +15,7 @@ * limitations under the License. */ -namespace {{invokerPackage}}; +namespace {{invokerNamespace}}; use \Exception; diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 12d2eb80744..5d84e0541da 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -20,11 +20,17 @@ * NOTE: This class is auto generated by the swagger code generator program. Do not edit the class manually. */ -namespace {{invokerPackage}}; +namespace {{apiNamespace}}; + +use {{invokerNamespace}}\Configuration; +use {{invokerNamespace}}\ApiClient; {{#operations}} class {{classname}} { + /** @var ApiClient */ + private $apiClient; + function __construct($apiClient = null) { if (null === $apiClient) { if (Configuration::$apiClient === null) { @@ -38,8 +44,6 @@ class {{classname}} { } } - private $apiClient; // instance of the ApiClient - /** * get the API client */ diff --git a/modules/swagger-codegen/src/main/resources/php/autoload.mustache b/modules/swagger-codegen/src/main/resources/php/autoload.mustache index 5ed11c11041..41e4790da22 100644 --- a/modules/swagger-codegen/src/main/resources/php/autoload.mustache +++ b/modules/swagger-codegen/src/main/resources/php/autoload.mustache @@ -1,29 +1,29 @@ {{name}} = $data["{{name}}"];{{#hasMore}} {{/hasMore}}{{/vars}} } + {{#vars}} + /** + * get {{name}} + * @return {{datatype}} + */ + public function {{getter}}() { + return $this->{{name}}; + } + /** + * set {{name}} + * @param {{datatype}} ${{name}} + */ + public function {{setter}}(${{name}}) { + $this->{{name}} = ${{name}}; + } + {{/vars}} public function offsetExists($offset) { return isset($this->$offset); } From f9f58596b8ab3cb840513ebd35efbdf730c688d3 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Thu, 18 Jun 2015 16:51:24 -0700 Subject: [PATCH 22/67] account for return type where the response type is in a list container, and properly import models into operations --- .../codegen/languages/PhpClientCodegen.java | 29 ++++++++++++++++++- .../src/main/resources/php/api.mustache | 9 ++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index af4867108a8..ad9ca3aa9b1 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -10,9 +10,12 @@ import io.swagger.models.properties.MapProperty; import io.swagger.models.properties.Property; import java.io.File; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { @@ -244,7 +247,31 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public Map postProcessOperations(Map objs) { - return addNamespaces(super.postProcessOperations(objs)); + objs = addNamespaces(super.postProcessOperations(objs)); + + if (objs.containsKey("imports")) { + List> imports = new ArrayList>(); + LinkedHashMap newImport; + String currentImport; + String modelName; + + for (Map importMap : (List>) objs.get("imports")) { + currentImport = importMap.get("import"); + modelName = currentImport.replace(modelPackage + ".", ""); + + if (reservedWords.contains(modelName)) { + continue; + } + + newImport = new LinkedHashMap(); + newImport.put("import", modelNamespace + "\\" + modelName); + imports.add(newImport); + } + + objs.put("imports", imports); + } + + return objs; } @Override diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 5d84e0541da..5798ef6f882 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -25,6 +25,10 @@ namespace {{apiNamespace}}; use {{invokerNamespace}}\Configuration; use {{invokerNamespace}}\ApiClient; +{{#imports}} +use {{{import}}}; +{{/imports}} + {{#operations}} class {{classname}} { @@ -65,7 +69,7 @@ class {{classname}} { * {{{summary}}} * {{#allParams}} * @param {{dataType}} ${{paramName}} {{description}} {{^optional}}(required){{/optional}}{{#optional}}(optional){{/optional}} -{{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} +{{/allParams}} * @return {{#returnType}}{{#isListContainer}}{{returnBaseType}}[]{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}{{/returnType}}{{^returnType}}void{{/returnType}} */ public function {{nickname}}({{#allParams}}${{paramName}}{{#optional}}=null{{/optional}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { {{#allParams}}{{#required}} @@ -136,6 +140,5 @@ class {{classname}} { return $responseObject;{{/returnType}} } {{/operation}} -{{newline}} -{{/operations}} } +{{/operations}} From 5c409884b95bd4bbdae756d03083c8a90d71038a Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Fri, 19 Jun 2015 10:31:05 -0700 Subject: [PATCH 23/67] make setters fluent --- modules/swagger-codegen/src/main/resources/php/model.mustache | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/swagger-codegen/src/main/resources/php/model.mustache b/modules/swagger-codegen/src/main/resources/php/model.mustache index 7f78311ade4..9e50edcb567 100644 --- a/modules/swagger-codegen/src/main/resources/php/model.mustache +++ b/modules/swagger-codegen/src/main/resources/php/model.mustache @@ -62,9 +62,11 @@ class {{classname}} implements ArrayAccess { /** * set {{name}} * @param {{datatype}} ${{name}} + * @return $this */ public function {{setter}}(${{name}}) { $this->{{name}} = ${{name}}; + return $this; } {{/vars}} public function offsetExists($offset) { From 3252dd0d189f692ec8c49cf8b1eb3e434388a8d8 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Fri, 19 Jun 2015 10:32:38 -0700 Subject: [PATCH 24/67] check for null array in constructor --- .../swagger-codegen/src/main/resources/php/model.mustache | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/model.mustache b/modules/swagger-codegen/src/main/resources/php/model.mustache index 9e50edcb567..86dafc99d99 100644 --- a/modules/swagger-codegen/src/main/resources/php/model.mustache +++ b/modules/swagger-codegen/src/main/resources/php/model.mustache @@ -47,8 +47,10 @@ class {{classname}} implements ArrayAccess { public ${{name}}; {{/vars}} public function __construct(array $data = null) { - {{#vars}}$this->{{name}} = $data["{{name}}"];{{#hasMore}} - {{/hasMore}}{{/vars}} + if ($data != null) { + {{#vars}}$this->{{name}} = $data["{{name}}"];{{#hasMore}} + {{/hasMore}}{{/vars}} + } } {{#vars}} /** From acdc5328fe5da0178024b721846912f08c749751 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Fri, 19 Jun 2015 11:24:56 -0700 Subject: [PATCH 25/67] deserialize thrown exceptions --- .../codegen/languages/PhpClientCodegen.java | 33 +++++++++++-------- .../src/main/resources/php/api.mustache | 25 +++++++++++--- 2 files changed, 39 insertions(+), 19 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index ad9ca3aa9b1..073c7ff1c96 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -248,7 +248,26 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public Map postProcessOperations(Map objs) { objs = addNamespaces(super.postProcessOperations(objs)); + objs = formatImports(objs); + return objs; + } + + @Override + public Map postProcessSupportingFileData(Map objs) { + return addNamespaces(super.postProcessSupportingFileData(objs)); + } + + protected Map addNamespaces(Map objs) { + objs.put("rootNamespace", rootNamespace); + objs.put("invokerNamespace", invokerNamespace); + objs.put("apiNamespace", apiNamespace); + objs.put("modelNamespace", modelNamespace); + + return objs; + } + + protected Map formatImports(Map objs) { if (objs.containsKey("imports")) { List> imports = new ArrayList>(); LinkedHashMap newImport; @@ -273,18 +292,4 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { return objs; } - - @Override - public Map postProcessSupportingFileData(Map objs) { - return addNamespaces(super.postProcessSupportingFileData(objs)); - } - - protected Map addNamespaces(Map objs) { - objs.put("rootNamespace", rootNamespace); - objs.put("invokerNamespace", invokerNamespace); - objs.put("apiNamespace", apiNamespace); - objs.put("modelNamespace", modelNamespace); - - return objs; - } } diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 5798ef6f882..704f1c5ebab 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -24,6 +24,7 @@ namespace {{apiNamespace}}; use {{invokerNamespace}}\Configuration; use {{invokerNamespace}}\ApiClient; +use {{invokerNamespace}}\ApiException; {{#imports}} use {{{import}}}; @@ -128,16 +129,30 @@ class {{classname}} { $authSettings = array({{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}); // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams, $authSettings); + } catch (ApiException $e) { + $throw = $e; - {{#returnType}}if(! $response) { + switch ($e->getCode()) { {{#responses}}{{#dataType}} + case {{code}}: + $data = $this->apiClient->deserialize($e->getResponseBody(), '{{dataType}}'); + $throw = new ApiException("{{message}}", $e->getCode(), $e->getResponseHeaders(), $data); + break;{{/dataType}}{{/responses}} + } + + throw $throw; + } + {{#returnType}} + if(!$response) { return null; } $responseObject = $this->apiClient->deserialize($response,'{{returnType}}'); - return $responseObject;{{/returnType}} + return $responseObject; + {{/returnType}} } {{/operation}} } From caa1b7f4111ea2bf4ffafdb5244bc364cece0442 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Fri, 19 Jun 2015 15:20:29 -0700 Subject: [PATCH 26/67] generate model imports for support files, and use them as imports --- .../codegen/languages/PhpClientCodegen.java | 27 +++++++++---------- .../src/main/resources/php/ApiClient.mustache | 5 +++- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 073c7ff1c96..7fb23157b36 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -248,14 +248,17 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public Map postProcessOperations(Map objs) { objs = addNamespaces(super.postProcessOperations(objs)); - objs = formatImports(objs); + objs = formatImports(objs, "imports", "import"); return objs; } @Override public Map postProcessSupportingFileData(Map objs) { - return addNamespaces(super.postProcessSupportingFileData(objs)); + objs = addNamespaces(super.postProcessSupportingFileData(objs)); + objs = formatImports(objs, "models", "importPath"); + + return objs; } protected Map addNamespaces(Map objs) { @@ -267,27 +270,23 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { return objs; } - protected Map formatImports(Map objs) { - if (objs.containsKey("imports")) { - List> imports = new ArrayList>(); - LinkedHashMap newImport; - String currentImport; + protected Map formatImports(Map objs, String objsKey, String importKey) { + if (objs.containsKey(objsKey)) { String modelName; + List> newImportList = new ArrayList>(); - for (Map importMap : (List>) objs.get("imports")) { - currentImport = importMap.get("import"); - modelName = currentImport.replace(modelPackage + ".", ""); + for (Map importMap : (List>) objs.get(objsKey)) { + modelName = ((String) importMap.get(importKey)).replace(modelPackage + ".", ""); if (reservedWords.contains(modelName)) { continue; } - newImport = new LinkedHashMap(); - newImport.put("import", modelNamespace + "\\" + modelName); - imports.add(newImport); + importMap.put(importKey, modelNamespace + "\\" + modelName); + newImportList.add(importMap); } - objs.put("imports", imports); + objs.put(objsKey, newImportList); } return objs; diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index 564bc1ddd66..4a3e50dd50b 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -17,6 +17,10 @@ namespace {{invokerNamespace}}; +{{#models}} +use {{importPath}}; +{{/models}} + class ApiClient { public static $PATCH = "PATCH"; @@ -399,7 +403,6 @@ class ApiClient { settype($data, $class); $deserialized = $data; } else { - $class = "{{invokerPackage}}\\models\\".$class; $instance = new $class(); foreach ($instance::$swaggerTypes as $property => $type) { $original_property_name = $instance::$attributeMap[$property]; From 1d59937150c5b79d192487fd2e9c7d007e4994f6 Mon Sep 17 00:00:00 2001 From: wing328 Date: Mon, 22 Jun 2015 11:53:44 +0800 Subject: [PATCH 27/67] add nunit test for csharp --- bin/csharp-petstore.sh | 2 +- .../SwaggerClient}/bin/Newtonsoft.Json.dll | Bin .../Lib/SwaggerClient}/bin/RestSharp.dll | Bin .../Lib/SwaggerClient}/compile.bat | 0 .../src/main/csharp/IO/Swagger}/Api/PetApi.cs | 0 .../main/csharp/IO/Swagger}/Api/StoreApi.cs | 0 .../main/csharp/IO/Swagger}/Api/UserApi.cs | 0 .../csharp/IO/Swagger/Client}/ApiClient.cs | 0 .../csharp/IO/Swagger/Client}/ApiException.cs | 0 .../IO/Swagger/Client}/Configuration.cs | 0 .../main/csharp/IO/Swagger}/Model/Category.cs | 0 .../main/csharp/IO/Swagger}/Model/Order.cs | 0 .../src/main/csharp/IO/Swagger}/Model/Pet.cs | 0 .../src/main/csharp/IO/Swagger}/Model/Tag.cs | 0 .../src/main/csharp/IO/Swagger}/Model/User.cs | 0 .../SwaggerClientTest.csproj | 68 + .../SwaggerClientTest/SwaggerClientTest.sln | 17 + .../SwaggerClientTest.userprefs | 13 + .../csharp/SwaggerClientTest/TestPet.cs | 109 + .../bin/Debug/Newtonsoft.Json.dll | Bin 0 -> 426496 bytes .../SwaggerClientTest/bin/Debug/RestSharp.dll | Bin 0 -> 167936 bytes .../bin/Debug/SwaggerClientTest.dll | Bin 0 -> 51200 bytes .../bin/Debug/SwaggerClientTest.dll.mdb | Bin 0 -> 15782 bytes .../bin/Debug/nunit.framework.dll | Bin 0 -> 151552 bytes ...ramework,Version=v4.5.AssemblyAttribute.cs | 2 + ...ClientTest.csproj.FilesWrittenAbsolute.txt | 8 + .../obj/Debug/SwaggerClientTest.dll | Bin 0 -> 51200 bytes .../obj/Debug/SwaggerClientTest.dll.mdb | Bin 0 -> 15782 bytes .../csharp/SwaggerClientTest/packages.config | 4 + .../packages/NUnit.2.6.3/NUnit.2.6.3.nupkg | Bin 0 -> 98508 bytes .../NUnit.2.6.3/lib/nunit.framework.dll | Bin 0 -> 151552 bytes .../NUnit.2.6.3/lib/nunit.framework.xml | 10960 ++++++++++++++++ .../packages/NUnit.2.6.3/license.txt | 15 + .../packages/repositories.config | 4 + 34 files changed, 11201 insertions(+), 1 deletion(-) rename samples/client/petstore/csharp/{ => SwaggerClientTest/Lib/SwaggerClient}/bin/Newtonsoft.Json.dll (100%) rename samples/client/petstore/csharp/{ => SwaggerClientTest/Lib/SwaggerClient}/bin/RestSharp.dll (100%) rename samples/client/petstore/csharp/{ => SwaggerClientTest/Lib/SwaggerClient}/compile.bat (100%) rename samples/client/petstore/csharp/{src/main/csharp/io/swagger => SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger}/Api/PetApi.cs (100%) rename samples/client/petstore/csharp/{src/main/csharp/io/swagger => SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger}/Api/StoreApi.cs (100%) rename samples/client/petstore/csharp/{src/main/csharp/io/swagger => SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger}/Api/UserApi.cs (100%) rename samples/client/petstore/csharp/{src/main/csharp/io/swagger/client => SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Client}/ApiClient.cs (100%) rename samples/client/petstore/csharp/{src/main/csharp/io/swagger/client => SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Client}/ApiException.cs (100%) rename samples/client/petstore/csharp/{src/main/csharp/io/swagger/client => SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Client}/Configuration.cs (100%) rename samples/client/petstore/csharp/{src/main/csharp/io/swagger => SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger}/Model/Category.cs (100%) rename samples/client/petstore/csharp/{src/main/csharp/io/swagger => SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger}/Model/Order.cs (100%) rename samples/client/petstore/csharp/{src/main/csharp/io/swagger => SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger}/Model/Pet.cs (100%) rename samples/client/petstore/csharp/{src/main/csharp/io/swagger => SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger}/Model/Tag.cs (100%) rename samples/client/petstore/csharp/{src/main/csharp/io/swagger => SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger}/Model/User.cs (100%) create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.csproj create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.sln create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.userprefs create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/TestPet.cs create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/Newtonsoft.Json.dll create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/RestSharp.dll create mode 100755 samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/SwaggerClientTest.dll create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/SwaggerClientTest.dll.mdb create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/nunit.framework.dll create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/.NETFramework,Version=v4.5.AssemblyAttribute.cs create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.csproj.FilesWrittenAbsolute.txt create mode 100755 samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.dll create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.dll.mdb create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/packages.config create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/packages/NUnit.2.6.3/NUnit.2.6.3.nupkg create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/packages/NUnit.2.6.3/lib/nunit.framework.dll create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/packages/NUnit.2.6.3/lib/nunit.framework.xml create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/packages/NUnit.2.6.3/license.txt create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/packages/repositories.config diff --git a/bin/csharp-petstore.sh b/bin/csharp-petstore.sh index a72a6cf84f0..c3fe78f0f36 100755 --- a/bin/csharp-petstore.sh +++ b/bin/csharp-petstore.sh @@ -26,6 +26,6 @@ fi # if you've executed sbt assembly previously it will use that instead. export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" -ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l csharp -o samples/client/petstore/csharp" +ags="$@ generate -i modules/swagger-codegen/src/test/resources/2_0/petstore.json -l csharp -o samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient" java $JAVA_OPTS -jar $executable $ags diff --git a/samples/client/petstore/csharp/bin/Newtonsoft.Json.dll b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/bin/Newtonsoft.Json.dll similarity index 100% rename from samples/client/petstore/csharp/bin/Newtonsoft.Json.dll rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/bin/Newtonsoft.Json.dll diff --git a/samples/client/petstore/csharp/bin/RestSharp.dll b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/bin/RestSharp.dll similarity index 100% rename from samples/client/petstore/csharp/bin/RestSharp.dll rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/bin/RestSharp.dll diff --git a/samples/client/petstore/csharp/compile.bat b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/compile.bat similarity index 100% rename from samples/client/petstore/csharp/compile.bat rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/compile.bat diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Api/PetApi.cs similarity index 100% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/PetApi.cs rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Api/PetApi.cs diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Api/StoreApi.cs similarity index 100% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/StoreApi.cs rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Api/StoreApi.cs diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Api/UserApi.cs similarity index 100% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/Api/UserApi.cs rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Api/UserApi.cs diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Client/ApiClient.cs similarity index 100% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiClient.cs rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Client/ApiClient.cs diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiException.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Client/ApiException.cs similarity index 100% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/client/ApiException.cs rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Client/ApiException.cs diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Client/Configuration.cs similarity index 100% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/client/Configuration.cs rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Client/Configuration.cs diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Category.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Model/Category.cs similarity index 100% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Category.cs rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Model/Category.cs diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Model/Order.cs similarity index 100% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Model/Order.cs diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Pet.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Model/Pet.cs similarity index 100% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Pet.cs rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Model/Pet.cs diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Tag.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Model/Tag.cs similarity index 100% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Tag.cs rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Model/Tag.cs diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/User.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Model/User.cs similarity index 100% rename from samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/User.cs rename to samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Model/User.cs diff --git a/samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.csproj b/samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.csproj new file mode 100644 index 00000000000..7a0b8f7674b --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.csproj @@ -0,0 +1,68 @@ + + + + Debug + AnyCPU + {1011E844-3414-4D65-BF1F-7C8CE0167174} + Library + SwaggerClientTest + SwaggerClientTest + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + full + true + bin\Release + prompt + 4 + false + + + + + packages\NUnit.2.6.3\lib\nunit.framework.dll + + + Lib\SwaggerClient\bin\Newtonsoft.Json.dll + + + Lib\SwaggerClient\bin\RestSharp.dll + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.sln b/samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.sln new file mode 100644 index 00000000000..dfb6e762ce2 --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.sln @@ -0,0 +1,17 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SwaggerClientTest", "SwaggerClientTest.csproj", "{1011E844-3414-4D65-BF1F-7C8CE0167174}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1011E844-3414-4D65-BF1F-7C8CE0167174}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1011E844-3414-4D65-BF1F-7C8CE0167174}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1011E844-3414-4D65-BF1F-7C8CE0167174}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1011E844-3414-4D65-BF1F-7C8CE0167174}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.userprefs b/samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.userprefs new file mode 100644 index 00000000000..4fa44c936ae --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientTest/SwaggerClientTest.userprefs @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/samples/client/petstore/csharp/SwaggerClientTest/TestPet.cs b/samples/client/petstore/csharp/SwaggerClientTest/TestPet.cs new file mode 100644 index 00000000000..8e6ea0f99d2 --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientTest/TestPet.cs @@ -0,0 +1,109 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using IO.Swagger.Api; +using IO.Swagger.Model; +using IO.Swagger.Client; + + +namespace SwaggerClient.TestPet +{ + [TestFixture ()] + public class TestPet + { + public long petId = 11088; + + [SetUp] public void Init() + { + // create pet + Pet p = new Pet(); + p.Id = petId; + p.Name = "Csharp test"; + p.Status = "available"; + // create Category object + Category category = new Category(); + category.Id = 56; + category.Name = "sample category name2"; + List photoUrls = new List(new String[] {"sample photoUrls"}); + // create Tag object + Tag tag = new Tag(); + tag.Id = petId; + tag.Name = "sample tag name1"; + List tags = new List(new Tag[] {tag}); + p.Tags = tags; + p.Category = category; + p.PhotoUrls = photoUrls; + + // add pet before testing + PetApi petApi = new PetApi("http://petstore.swagger.io/v2/"); + petApi.AddPet (p); + + } + + [TearDown] public void Cleanup() + { + // remove the pet after testing + PetApi petApi = new PetApi (); + petApi.DeletePet("test key", petId); + } + + + [Test ()] + public void TestGetPetById () + { + PetApi petApi = new PetApi (); + Pet response = petApi.GetPetById (petId); + Assert.IsInstanceOf (response, "Response is a Pet"); + + Assert.AreEqual ("Csharp test", response.Name); + Assert.AreEqual ("available", response.Status); + + Assert.IsInstanceOf> (response.Tags, "Response.Tags is a Array"); + Assert.AreEqual (petId, response.Tags [0].Id); + Assert.AreEqual ("sample tag name1", response.Tags [0].Name); + + Assert.IsInstanceOf> (response.PhotoUrls, "Response.PhotoUrls is a Array"); + Assert.AreEqual ("sample photoUrls", response.PhotoUrls [0]); + + Assert.IsInstanceOf (response.Category, "Response.Category is a Category"); + Assert.AreEqual (56, response.Category.Id); + Assert.AreEqual ("sample category name2", response.Category.Name); + + } + + [Test ()] + public void TestUpdatePetWithForm () + { + PetApi petApi = new PetApi (); + petApi.UpdatePetWithForm (petId.ToString(), "new form name", "pending"); + + Pet response = petApi.GetPetById (petId); + Assert.IsInstanceOf (response, "Response is a Pet"); + Assert.IsInstanceOf (response.Category, "Response.Category is a Category"); + Assert.IsInstanceOf> (response.Tags, "Response.Tags is a Array"); + + Assert.AreEqual ("new form name", response.Name); + Assert.AreEqual ("pending", response.Status); + + Assert.AreEqual (petId, response.Tags [0].Id); + Assert.AreEqual (56, response.Category.Id); + } + + [Test ()] + public void TestFindPetByStatus () + { + PetApi petApi = new PetApi (); + List statusList = new List(new String[] {"available"}); + + List listPet = petApi.FindPetsByStatus (statusList); + foreach (Pet pet in listPet) // Loop through List with foreach. + { + Assert.IsInstanceOf (pet, "Response is a Pet"); + Assert.AreEqual ("available", pet.Status); + } + + } + + } +} + diff --git a/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/Newtonsoft.Json.dll b/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/Newtonsoft.Json.dll new file mode 100644 index 0000000000000000000000000000000000000000..26fdaffec145b1795af118d07ef764406d78f6f8 GIT binary patch literal 426496 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

BWZ_eV|^M^miQ6%*;qfy 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ΝZNt?r4^ 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 We5D(VilUEh|3}=%-*#gGP_xT_I literal 0 HcmV?d00001 diff --git a/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/RestSharp.dll b/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/RestSharp.dll new file mode 100644 index 0000000000000000000000000000000000000000..a7331ed6e2379bbb0b9680ff82d86ce4cb1b03bc GIT binary patch literal 167936 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 z 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%0DIhxI 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 literal 0 HcmV?d00001 diff --git a/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/SwaggerClientTest.dll.mdb b/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/SwaggerClientTest.dll.mdb new file mode 100644 index 0000000000000000000000000000000000000000..a7a6c4d4364bdf59f6d3b8fd0b9f68752a88cea2 GIT binary patch literal 15782 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 vQ5D?esDd7WS^bETdzaIP_?WJMB literal 0 HcmV?d00001 diff --git a/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/nunit.framework.dll b/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/nunit.framework.dll new file mode 100644 index 0000000000000000000000000000000000000000..780727f219d08aa635e12a56a326850ef82dbec5 GIT binary patch literal 151552 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%0ANEfz#`T+5knLeJ%5cmKE0sc26YHG1oPt)XZ; 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≺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 +[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.5", FrameworkDisplayName = "")] diff --git a/samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.csproj.FilesWrittenAbsolute.txt b/samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.csproj.FilesWrittenAbsolute.txt new file mode 100644 index 00000000000..9afb7990f57 --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.csproj.FilesWrittenAbsolute.txt @@ -0,0 +1,8 @@ +/Users/williamcheng/Code/swagger-codegen/samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/.NETFramework,Version=v4.5.AssemblyAttribute.cs +/Users/williamcheng/Code/swagger-codegen/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/nunit.framework.dll +/Users/williamcheng/Code/swagger-codegen/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/Newtonsoft.Json.dll +/Users/williamcheng/Code/swagger-codegen/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/RestSharp.dll +/Users/williamcheng/Code/swagger-codegen/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/SwaggerClientTest.dll.mdb +/Users/williamcheng/Code/swagger-codegen/samples/client/petstore/csharp/SwaggerClientTest/bin/Debug/SwaggerClientTest.dll +/Users/williamcheng/Code/swagger-codegen/samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.dll +/Users/williamcheng/Code/swagger-codegen/samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.dll.mdb diff --git a/samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.dll b/samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.dll new file mode 100755 index 0000000000000000000000000000000000000000..bac89714b9cad85af8d64fd3230169073c376c63 GIT binary patch literal 51200 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 literal 0 HcmV?d00001 diff --git a/samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.dll.mdb b/samples/client/petstore/csharp/SwaggerClientTest/obj/Debug/SwaggerClientTest.dll.mdb new file mode 100644 index 0000000000000000000000000000000000000000..a7a6c4d4364bdf59f6d3b8fd0b9f68752a88cea2 GIT binary patch literal 15782 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 vQ5D?esDd7WS^bETdzaIP_?WJMB literal 0 HcmV?d00001 diff --git a/samples/client/petstore/csharp/SwaggerClientTest/packages.config b/samples/client/petstore/csharp/SwaggerClientTest/packages.config new file mode 100644 index 00000000000..d4e241a20a0 --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientTest/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/samples/client/petstore/csharp/SwaggerClientTest/packages/NUnit.2.6.3/NUnit.2.6.3.nupkg b/samples/client/petstore/csharp/SwaggerClientTest/packages/NUnit.2.6.3/NUnit.2.6.3.nupkg new file mode 100644 index 0000000000000000000000000000000000000000..61e3a5ecfc122b969532f236ae4d08f73eaf6a67 GIT binary patch literal 98508 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%0D84oaW6e%A6a8UDh7;bSxoYne$N4r{Y{DLv`~ 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 z·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%0D|(AT|jZ@uFm#D0a&sL-FN5NomG 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%0ANEfz#`T+5knLeJ%5cmKE0sc26YHG1oPt)XZ; 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≺zl~odM_}pNxJI&yx~|y;NNuk%yg!@(1;U+Z?rBnh6}r!L5h{HEpml;z8;Tx?l8fAj; zjn?JHAxYQO6~;9|_(tmrBczO%@N}TAy<{W`!Z%u9GSVgK+RMfwLHI`N%f?Pg4(%1A zQV_n;`ify&>FnSXWzVv=)SKw5~LU2*Nj7R~eHzu{T;@HCBo^e53VMqg)Wa(fXQk zUQ#!$%jS_}1z=qf!vQ zr@G#-y}?Vs_f$6+O$FhbsT+;Hg7D4MH;sHj_-5)`#!^A}X6hzmH=`0;gNFM(w-`&; zV4fwm_6_%VY%yMCge!ER{cU3}C)nRTe6|{=7#$>dO4tft&w}arezeVSFv8v5&u6>Q zT2hG54kKAoJ)fOMzNGtob{UH##rwQtY-LnJdNq8+=UwACkAu1l_1SGyN=otBW5llG zrDI+88CxZt@%+HZUypGM$n1urefArt7-6k1dzKrUHt=+KRy<&w5`<@|gT^IBd@ugc z2;YdFeAoWaXw8UU?IEKxBfgIvHhMDR?RnT(DLk=ehmF&gbRQW%S<-!M+^~3lY^1*F zuGtYIUl7*p6XR1xyu72vc@c*t95wvka;N*$h-Sn+j~NXa;m%y_am6_V~hB#HbuvaI(*FhQMjf1$8hPIjIX`9HXp`huEdJ1}uQI4Qxj1~!6 z&1k2f&5TY7`hXGsU<01djx>56$_p1XyZ-Y&Um4vcz3B57BVW=RK3^LvC2jLLWgL;T z$LAa41|vQ@zBL-XjU^l;c)$5qBT*2x*=gfEqY~l~dBo?8@zYlHEFlq*U;2D!tl7rt zM5Dj@oHx2}=k)hRmwhf7(K|SKHoocelW{{(bYtE3nsIw4#w{SN8#{b&8oPIK&mQ3U zo6-Fp7RT=Y?uwp1s2}iK?{(K$!{QDqI~uR|Qq0?omcR)x##c2R?_xTnM!uTaRMLIE zx|t}c6Z}Tca7n#$&7G>JmhUN=QBD8f3LmX%WiIwaU*>_&2meemsu$Y zYvyA%+>Lc9B_A|~`+jo~C&)9I1ehxrVF@|D0p=z~yo5mWZ!)fzcaV9_5*KVXdJpr& zbR)e(%y>pTU8p%u#wC+5vq;h;-!OBj@Wh!DVJ7auT=>cmX>MbLc{cHkGLMNk^o%y| zSUh7)@AqA$H}R}vhBM-KyLHV`GA^0Kn%PyTunNs*w1m`eGSxTM?6ep2M0(b@fq6qv zyCw^K8=JBFc-$jRmiRU?`wAM~WVvrsbF!f9CM$iLnX4J`cio$tn;790722Dd`x)`8 zZDF1kgxA;7Z1Dk>z&%@;4>RJP_n9LFq38YP7U|iQqabjKB$7>53X6|=8jk(tcmFwYFX$z~?^gdOj?ZL(P^=<}xD`ebvy zpfgRc+nzGl2)YSzPnlZ<`8Uhjb^YS63*sFKk+1(z=u=1w zNY`dl{YuRoLFvtA`%O1b37XdINixH1{S8m|Mze)}v&@x(-fgzrZ?<_`(1*>|`pq+s ze9Jw*YPQ2~f$8;EPUo7v=eN+bokm(ferf8n>(?D;p0<1P52*@+SV zB>P2kB#$G*n^XT6%@vGF$e89H{wvIPEa_e{k4ld*WgcgQr8o9kWmbwf9J{ZXwJUi#oGWE!XGZ)KwAxH(gwL#k{9iXq z1#NGRv{IzQTwWLbUarrsy~FPf^Eiv+r^B_T-*;HTB66_#PT#fWkaL{AXddRj&OF43 zx5P&C5+kf6-c{=ob+uS1v=k!+d z7$aV@ZRQO|mHY`I(~RKnVO!+;e`so#u=FLiZjkP<87(Q@ z|6?;=(s2Jz%pr^xkQR{cQ**M2ORhJ?|1)znBfN&XUZ0!0McjZEv;4m>k2B)WLynu* z7@bq_na*+3>$20vXhwWTIAL}XguU{mnIb)lJu1u`M&oUQVZ_Jv74sw`zCT_AaWJs&cU<8pKaI7Xij$Y zyk^ERLeGzYdRjbxF>@@QznC)_@iFm>xk=I)&+Fz$_n(u3_m|LNd8& zhBI0MPYbUG+%)3_g|$R_RC*TLZ%bULDLzP3VM#wPC?5UT@tjKQS^15=VnI9f<9n0Q&6v# z@aeJn8YgzOx6R#*_&xeO*^GEDifs`m+bL)X#kN7vrIv+u#kNz>ZHS|`V}iU}722uo6r+Ro$X4q;RNFN{ ztr%fVaGZ5%6&tA9ylx`#dne82V04gRoMyuq^ek<4)?2qVws;!0`>Ie+kq$i#TN)#N z4W=zq#9^MMZ7C-k*34!*BnWF}ljY5C)g;hnyTRgk%{*-67S@I5>0xWg=paE)4_g8w z?&)RgDLtEbdf6rmPb}Tr_N9zVvisQ1i#V*cug&%wyIO+eXNzXU%k#H2tU`S)p8mFU zOI(0$zKFw`1=u$5IQFKR!&WXmi#;5+Yr+$27G&#t+g*CFEu9fBy_PMf3e6Fon68%X zYfD^+?V5=9}Ul+-q`wk?_ww%LP$;kITnuGk~e)=pB}z$jZ+i)V~& zfQ&2lsB0S`scm4aEz{yz-&Q2!iai?Irb%iW*vR(0#j}a*_XB?21DgRUX_V^|^on&s(O%pbo|Nr7)|b%j-yTTP2bc!{l8 z=~yECJ{3#rwkQO{3hBUn9;z000i_0$^lyd zehU|5)%sMoE3B=!Cw|lNy;D`UTRjz43S}+qYCT?m-j5jmb3WBeaa~Jw`@g4jcaOWS z!fkPl0k`Gf?~}xO&^jjF7KLD#%c?E^@AJX$-lS|!RUJ{)?f4D4E>COt|J_vmp)WKx z{&lf>xLZIa?%1lWf%ck~{~h_@m~qV=YfbokbX%&H{-0Ftmid2otp5349s;AN>e}MA zCt3d!G463!o1;|V&W@i?{u#+r{gK4d z|C!wWjDH?GF#prztB>`m(Kn&2 zzu39D=F_%+E&u>$57`KGhg~D8y2aJ1Zo5L<;r}WX zuc7sB)NOIyce^dtk;(7G|9KxAMfYkYx82oN?lH{AQq|83taH#kqN?Ux-EJL|*6{z- zRL9szu=bAIq7V#oS@o&NzuO0ALDd%HCA#gdTJiZ(J=Qg1tK0w2rLvACYq zwVYpDSHwBkhl#J>Fum{Bw5v9Un+_zk9^~4xjDf@0_9x13QIZpZrH* zUp9KVjAi*)WmA>|p0QQZ8p0am-@g`7tIhur}fK8O1Do7t3K`eiq7yu*&8* z{#vfPR{VPZ-F4%&;x+uob(_fQJcY?;n8f=Xg_K&t(^=TvdahRDE#`g$L18WCdIG@L zRlXAPab+EEf7I_*yLEImWFyTQ%fqu+-4-%=8FmCpR{X;-k6p)n_{xkk#riD88dk|I z)*AeM5AOd*EA}d=VbxWg`&;)2cUUDmSRMW~3$Mcw)+W1IK3tZwa81eE>SZ>&|IGSO zvz`C@mP>3^!QT{B*e{Dx_~m5`TkH0ZOF71_?j)1$++6w8ysp<+&+`i!9Z3Oa44JYg%iV*TGsYu8Iob z79O_x+}lFox1{fV6*c|&n#Sj#HD_y>m(JTzZ|%+*S2KlhyC1Xjd#*o{A>czvZRYt5 zYZL1##7n7ZshJzj<*I#j?^KkyOX2%0{H8W5m)mRR%v*zBJCFTmEj344%~JmH8*bsO zefWravn5_>6tnOV%VT+%`&jMPwA^0voXk^M_bJ|be@6ay&dGl!f9tMY)8D-wx>g46 zV;!qCTia^kqZDTch2I~?wsnV9F=u&hd>#0s)qszDK4PtCT(d;XhqAMZ%AQMWq$L|a)$M#$`7@q>l!HbdxM$89{Bk{>i+C(Q^K|?JPhL0c z%3uxu(N$aRHT|uYKMM04tg(N_g0qQ|n(KMZb(LFqpSo9gm2_t9P}A~9yBi-5JRj?r zv07@D{%2D4U^U^VyFM&z?J2ZVG8pVC8O35TPuJbbIIw8qL}#@>!|Zq}uDU+gY_UJu zp{(PX*U&1hWz{^B|DUwLxfib8wY%LrtP);BYhVAFE1CfJ6qFRRI}6^|R!fz#EPeD} zw}$Jij&1I$o4Y>N*s9@KY&=-&FppVyPr1i-)iJP^)t~n-hACOZQoX`t8AwXjfm8_} zKYWL>jt9J7_~Ww;znif7^EqPOHLS6Gud!PAj%ls`zaz}|-)Ai65Nz|RZN)9tR^r$4 zNA{ZY>z~cj+78ya$#+0rI+vSRe{uhsyJSs&zL%k-#Fy=B*0QW&p1*Z=oM?b8!zFJw zF1h88dWX*u?!(VN*0elqP0L4)wG?X@pAxwKn&4e_?fckRpsPqQSqrvx@P8XQMz_QN%?kdV)-I6V`aTvu%)+06 zEcW<{$umq|VDbu+HW1vMgNZC8QZ)b{nDP_W;!p?yox zDtgEF-Jl{eH(-f>8adJSF!*0=`)SZx`fFRXb5Hzc`6SxLZ?X@@o)6kZz2a^|ZupyY zyJ#>A<1f-RV%Kf;3Qfa_eAg&7Mny@#bpE+fqyde;;y*t;G49p z?axrd%MTO;V-Ce0MaqY9lfnKml-`OQk6Z5%s+?%MMh{iKikob2r2H-JmEcxTdXl{r zxg56+!pGzGF-tNDWjVKE{;in5qGDO?Se~s=+U@GpI==<`Gkd5yzunbZ?I5?CwUX$z zb{WBq)T8Z+JsPRUg@l#?iypFoeB16iwET}C6O>G7jRfUxJCwHewL%gUycYEQ(PI|% ztk*mwi3YTP0Ay)ghmaB&16@H5XxlXeeXeM1z9e)P>#26o0!u=Z z=)Csd)=r{}AZ;e})I4u&=e}VmhcTHRR-|rgzdbCJ{WUnYKYafhYnh?Sm+k)&W>+q@ z|6ABl<)`*PfW+9z}|~B6;<@c*jDxyI&a@&|t9l2B=kczpd;Vx3ZdVC5av8d2fYpUz-%P6}~TR zp7(ARyPL)CX0f|j>~0oY4zaEL9Wa(ohaZ8NGSB-6!I9%&sT{1fo7G_*JR=k(r9&jh z(H-hVU@x?eutPuQL>y;x=M>97LHV`qx`;|ho8x;4WH0Y)AV+#BKJXy4T<~=WRiUW z8Sj6}6WcHu{yz3xhg;B|&o&qliSo(FB>GE-$sikqltJ3N9kzf}Rg^85}hZe6dM+UA;&Be{j>j>7f>|!acLbjo+jfa=rQD3q zjt(cZ2$60WFkbu?nGs0TqN(bFA$L6*h^#k5j! zMkLYm9mBu^-SvXg?_?9`gUl zKT-Lh#XkR@?AsDE)X)d_$7HB=m~6^q9FvJm4t(&Vm?F03EQ7R7JeRTAx{S?Je+@@e z5%e#tr6Ah|qI@vWMr`CE`0qs$LHdy-;zOE}ow^Tc3E%GSLt2xgAmfN)*hoBy1(^f> zKBSBswfm4YM2A06J;`!7#d0_eIoL=gnG5#wRSPjzlNSR4L!XyEXz-u>j6h;_{r3eI;aPbFPKgxx0vogevd)>7}D8+I*)kPMLmf) zm=1&MM803d2a>bQzccY>>FWx66LKM@Gx$vf|Gl6Wk~@KE3L&1rTzXtjuX;!PQPRJMP;~|}yo*k0P^p=pROn((p1{(9(&zOXs6?VlSSg{U69UFr(m2=qmAwpM4ssZ7@nD+i6~PJ<4F zegCfK`HKAfxQ_Mb zx>D$}01+Q3;vHOTL0sPnY}yEtV0{0sGI(6}B|!o3{xYa`+x5ZqSiIAL!mxINdT15dBTbB^uEb>f3u zr#-~=Y0y|sX(!HQ30#*y%ylI!kXXLfh3nX^Tqkzpnsn#w70vYbjx^BdUz)^q*&|$+ z_u#s+C)b^NiTd^C9NUNM#J*go_2as%?54^SQ1R z8h!D5Hx=iTuBH=et#82ir_9?Cti@7cnI_+r@KZR?pgzL&@1ec2VX zpUHK((516Dr#;K{UeGx2PBZpvi8;*^Rw;j72?>k745#$vV5EK#=85A4TIH+aN13~dY4+nJ* z>K!yZ=*ggxpy@#yf=&kg7(|2PgS!Ox3oZ#>82m!;>fkqncLaYJd@T6O;ID)K8eAEC zKKRGr>%pX!UdyXiV6D(vQMDS@A|ak3;UNhj{X!aq&JJB3x-N8c=+4l+p<8NySKASm z6gDU=1N`7k(h z4ksggN2H*FyoqR}kl0)P@a)RuGQFWN$XlfiV49=??9g8(WHZ!@E$(>BT$K(f&djsS$zl|WzIo<~OqhlAy8;BT$K(f&H^F|G$xoTAU~;3yf0y5S8m>=4MN;hj7Px#ZggWJYKYkR8IY4oOUoWippZ?ms{L zG4NRuj%VA+5m^7yh^Y|fJ_UZ5c6J0_5pUbIk$;6)ETNrv~}q^;&z1*NXR7bS&o6Bo_OZ=gHIZFfWVOgy+Lk4UOFnwY8?* zQ4jOkUk~TYhfE$}@bvRLf0Njzd!X*$sQ9sO=ko3kVvzeUCWC@eAn4HJtA|_WbS;pjMCM$g( z_QMwV2IPtQcWFMso$WYo0WNq34WEgD)GMwHIGK#hV z8BN=QjG^s7)}b9hHl!UvHiBm?lr*LZAe+$6Ae+)IAe+%{Ae+Ne7fM>t9w1xNULaf1 zJ|OR-{XpJN2Y~EO2ZHQR2ZJ0yhk{I|!$1zCkAWOSM}QnmQ$P-(sUU|^C&)+XD3HTw z2FMgT2IO;eEXesZ8{`5y4&?JR59C5x0CEv61i6?Nfm}i-fqa2J1#&5U8ssus0`f&V z734ZP4di+{1LOue3*<&R8|0gGF33&vIgp#_0+3tiLXcbOVvyVD3m|vUWw3|u1WDl& zlI0M7hsoXaC9u59J_y$W32(co`ym_(62^df0A!Tv z3Nlqa12RoL3w9?+N}g1|gYYPjl%%WQLpTE@C8N~~5FP`Pl1%j?gvWxUBul*v;cSqU zJ_l$GMTSl1$zNVO2(_dK)4VjB@@(NAzZ}dB=sg(CNlZ7`Wu9&sCOXt z8TBrNOF$}Qx~eFYOk;9}3X04GNy#i#2l=dOf}E|whh1b2NJ{3ao)De~62`6S4dMA9 zDOs-if?T2cgM3vD1p8|sVbrNXAUCVEKyFb(L7q{=KweQJK;BWKKq^`c$PleA$SAEI z$Y`wr$XKlr$a-26kS(=lAX{lIK;Ead0(rl7KgiZv8<1_awjkrQb|Bkn9YD6%I)dz| zJp{6omH;wA>kRT?tqaJ`S~rl1S`x@ES`Uz2wO$~*X?;L;*ZP4>(guKhTpI{7OB)PV zlns)SaoSLj)3sqBpVuA(xl9`Y@+)|yl704C(Yan0JSA%?6e*@$z`dW}{_4QE0bs%B2(KkYP14vkH^tV91sc#0kQ-2%e zE`1xw!}<vJ_*A<#sRJkfR%D)bzazd`I}f@RQ*`gy%<0k0_5g5^+4@R77ROwTRmh=b|5uc_bz+W=hN(F>l3a zQ}F!*1KutLJtsnpwOv8JB1!4bf(Y+LKg~MB=oC7r%+zc zSwhbhdV$c3gUs zCP_%m&&bY7PRSkR%+Dje2ckz;mj_99=H(|kGo7PS@|`3hFVC5qPdaC3<>lw5WMt)c zO-aqq&Mm5*s=3=EPb7jOx;ry-oVmyaV==Fytkk5e@!6>n&3gkN{6IoKrqQ?k;s$7W1~-~dRSk&-zmB@=2oAU_wf7e!Xd zgn_t53@49fggN54C!t05ZbM$;pOca1T?S#pcXQ&COt~;WmmQdZpy2rW4*~&NSI- zZa;|1%t+0!6p=J4D?8We_DIS~%`8ZBLRwUAd*95I{3o+>$GR<@p=k=NN&DtzL-Xfb zE~#_&*e5cwQlQhJ6Wl5Lrex$6X5?9NAK)BU;LOUe;?*l)o))CQ9aBVLoG_Li8MbxcloRvEn5Q`rTUYKgYY8<3pfu9?f&>t4p>^jv33 zn%kN6YxQeLf+?AuIo|1B5-sZ|8JLyl%s%3w4F54kNrTPD+9U$Px$3NXDqFlqWKsU30U?-ZLUO+iG@o*u89BCcqL_ zrD7?08L1XeUeN(goJX)GL#dWX_mX>0BfID>;|fwT?->n7wm#o85|U+%PsxO-dC%xR zxoJ+AFZYZaQ1AqF#yz8wQ!+D)px?&kq~vDgWoNmTTW)dYx;WAKWC|=Y|E1%|Ry8y0 znw{%TSH;0nC74;zENq~;c4g-3+K?YE$jF2%Bz$|z&V_Y86<&0a8+LVuEImt<+s25izbBa+X_bbw|GCS*$e-U9!^h2501_ zTYRdI6~-B`u8UpK#nrp3n==arXsRn(xI=@wEY%WJ>6Mz^!oqgF_N={G7vNWH?+9#J?x+O9RIxZzE)!FCCY8C7Wq21dgYB8n2*Ph z-YLB;nfK1dxn9L!oq)XyGObGhB4mvtt;VR34Zsetu72YOQx`$^C9&x0-OJr-So=Fu z3vzL8z!{1i1Yx<(<_k!F=aaCGK(pYze=_jeZLRgENY#DJr$J5y$;R&(@0Q=i;{S+J&9 zowLU}tM5#(vgGDhpO~mXedRGvQtV`jyBK+&cl~7FaqE#z6)g|Ef2^kg;$_ z@CO^7Yk0U8X0h8#bT6IK1lzw1^X*h3?D{f1z?u0Z9{_ME(kf3S(&Ao`q^WmymeT_H zGTbLu263cH7yunFfw!SVT$3g6dlr~FvMUKcw_7+XH5-rac^TvJ@Gfqb1{9>G!ouP< z+N95I53lLtF~6Lw%H&GFuq-~<@sBuNQ)zYXIA8i?N&cZM^~ z6L>m!7;e3@gd1$Gt`MHT@?fbE3msb>^GM&6JlJI5m?`=b@^^P5OskZ9@^BGcEIWPT zJtN%SC1yMGV5+h4!e$cO6yt<~d|*oh;2K(n{%WdO1xS9Egt=QV#1b0;;BE-(hY_2d24cD-Pp2a6LeA~~HO_qx15I7aW6P^+5 zOafu(w_N8~I4AQY%nV08w$>;DZ7~eY5j2@?n+W#p0tV3DB?T!MhMcd}U_F znzta#Ty2%+XT9WXu_d}18c#OXuxM=XOUUo(gaw9m0rRSM>R~RuvcUs;v=97|gFHc5 zf~>cz4Iei`9x$54jSSX}-I_pNc!}a3hV*ideF8dC9)<9bj;k4LXY9O=iP%=_nt&n# zQnFpXJIP3Yy5ToKABcl3fa5XL*pYWa> z9?~cnsT_o#NS&1Zz6qbMdr4I3*(=?jrj-SuaU@9^TgD6D53P z$96#{839F)&&V#oQx|(sIs%TmaG=H0H)DL#ius8uBl68d&UAk538O~kvWLU&>0Gs6 z@?-*NeH=YqGgIJ+Y0V6)L?_`b542D>XFiMsnRgx;k?nez%Ljv-Vf?{`_sNBE01sQm z-i9WE7I8-m&BO+`GtF&qHBK5Ckz0^O#6#kO{A{>jXMUIQ&?=T<^Ag6x?#FhIE?IC0 zgl()>O70juOp7+=8z>H79;(qFWCSdl*kL2`*aKN`Wk*R^uU%_J9>3kfY2b>2iNO|0 zi%AS?zRru)LTr5Q<%91tas^4svjknE9m`;gj94#R55CzrPGYC}41AOgb-)=9VOVvX zDPsvf5@$~0{88nmR34$BPNQJY&B~Y8P?cSqYP)j(T_!nXm~RbhZ#*Jk_V~7gJYpP6W1w&)e7b}e$e3_gejR->`8fiJLsH{ z+@)Ke{z+X15cuGUjg36wWNWVM&h#1`>~fHu%XZNkR@RjHu8vJ}fBZn;E`ZHEc!mm# zFD@nd8L)9>{5j>St3@eC5>X3a4=fOh`f>Sa4zIafRShCvHFqfOhdXABM0y zjCQg4pxF|vk~tdz=)eM)2p6~vC=iXVaJ(qt!7(F7JPf-rZbKRWtG#oLjq^J5`uj?{(zHMpiGl2{KRAGk-M0P^v@YOn{XxC_{?9pQ-gh`u z>`jX;&{CK4p8I*ubDs0u&UxRdEzY|`zTeLLI7nxS2I|ZWBXtzSsRj5WKrq777njW& z@1`%*IR%`D|C;G*))h{CH?g+HMm{2M1o}N)>kLUJieIZzNI^=AulI69?bb&QS9a#3RFH5$ZSErqptGj4qr-je!49ktXd zq}ya^nG*q5DuG+67K}=mOjX1*MUMv8N+&>CUaI)W`RbbG9fi7em}Ci?pOK=vh(`HR z+q}lt)~Z(nev)YD+GAaPTg>xaA2-<=vV#rW8rxTnkXS0B$rj#nJg$=Tk?LA)-I5}v z7E?9S^7jFxz|7gvd3$LTdF{E>=CCJtrjViSrI5UwZD@YFX|P?-oxR?;$JiUt*{QU# z9kWK^!+1wq!XyEr7N|Aa4@+`R*jimg3y-~1 zaJuffX((4qP@?1ZfTkoKSeTN zsU+v%T6T)z<7>6liFcSoI;ZVK9M={%0BR=u#us$((Gr73gfc_?wHM(zEvzG1+5EOq zFGE&(fm5}D6h~UqZCgSBw8+IP9Uir&Y^0*|7H46-GNO)r^?=~GN!*QwzW^;)s zLM(#*PI_xR{@}e2FbV_ z4Yycrte?8rI3IMh$%bD~BdBo{JrEC-&m^ZRwni+d`CU%e<}Y&CYEF)LeBaguJ8bR( z2x-{KzR*ioP6OiSScSkz#3M(lt<~CYQPhpk*iyhqk=Ct4@?adcSJ!Tb;iL~?xoQ-T z)wh()>r%kv^6~m2NUVX9`G#A?HO-3KIUdSE@QAcLSqr!i8m@8i?0kIp_>|8eUaBb8t&~Oldq5ZRM%-7)uzv<=PH(uq9*6pVcHCm`)dy zV@60PR*nFXMdkR39oiN}glSb~7oiJ9PU!>_W~cbk>Q$flAiUYfj@OsDOXuU$0c)z- zhDK$~)aNd63omZ0z#aT-(|UU-NTAxLP&049Q>L-@TPA=`by}B)9;mI`y!~CF)&xW6 z$q`Dr^MI8$j2Ids3T*m*>T%j}%5BpPQ`IE}F$#`fbwWJ30IRi}^|}skB3JW{K=1x# zKSs%D;LFzvnfrJw!8c;ch%alUxEZ*(gsafFjKO`nR@b=+0)kT#Xc*Npm7!}D?KxgU zZ>tm(cweF}W)*~7>tWWyiK(f{Q`3{v@~~)iwuq&P#$45IbFHtfEXwrYL?AXNVGt-m5F_F@fjFoA7 zgpS&XPwZ>EeAS=m06@9vJ^O*>W3Z_8N%?rC=roek*^>*Nh=qC4j=9~!@h>`4 zaBj)qxlr?+v}zftHB!yD0EHio6%GKjd{;P|tYKt*K9TInR(*ecIbB_x&{y9MFP%7P z$43i-t6v&(-n)3@d~J@Cfv{MxCx7;2*J2igG1f|=K**6#@`!FzwA@Y8HMY0>m7b*I zj99;I7LYvs#)v#3sTw3dptYn3i_?uN!E9af|R zSMaKAOsGI-Rdcm@-L~?D=?sA*O*b~smQSZu-lkxgN+Yc}wun8THN{a{jZ%4DG2d6{M?ch*TQQZ}BSWh58j|@knKET}pX8NZd{XM_mk;ilmR5N8U?))Sx(t6@P_z z$xa`k$Z-6%=AFV-J}a@rErKe>H0G9Wad0u+cuR7Nh0RBGU3Zf@JI{$bG0~k0$P&>k zhubt{W5-v67^?*HCJ$TR&L4<|MA_l8VQSMrYgV zfquxU@jxq91ZB~Dl2_d&dre}=AB2mQfB?uzMZOY~6yJUw1fK?Ue*F zm_NgyActFjegiF~b!Toht;UKD6_L{f&h@#IBO{Hg>#oX-&FXfS{kt10h)r4EW^3RB zPv5MpCAVIx;acn!z6*l60HhFnidN^ji*??i0!VGu_nN0a+r?k&V$qE9WU%KhJ?U;TQu%uOm@ziV$*~eq?G|GHbD3 zO}}swHVz{6A~?9J1Jjkukhk8^GPSvtFT^{7miX^f)IBF-mccD4F#f@&K4$7ms2m3#8EiO!Kh2UY7h&KtgK#L6Qk(tjQaxfwIv-acL4AZ zQ(;?l7Kk;-R;Lh^_eQl~84LAu7ZJN{oowMinheI-8ocL{t+vmwMyJ8r6^o@%8k`4) z1oZQ|nU*csx4d}9HDxXVBr^zut1;I-me(ay7Tp9)Xl3nwT@DpRC)KwUKy--wz=XV8 z!ri}u+~W#Q083ln`#&Xcm6Bc@auCLMkICK0PdZ3FC!q(aX?8f4#>unnDmY65fi8C~ zaNP!q8=13vcK%WZ1m&5Xi4Z#wG_Ip-swgeE5|FH>3|Tg?go7c~4`*+358U8JqOWXM z_0_t}_uLy?s5nXum%8(>z(fROz!OB8`oAiXs>Rqbq z4Gw9T%V6AmG;W4jnTIo+3wd{E>+FWxi6&|6P|CV**wP!3DUI{|g3uZG@uZkK*U4Hy z&q_CFrIP#^lMM|#V)Z5O&4@zQx;}cp9iKs92S3iePwherbsjdo%Ju_Ymmp5GN_q0F z%`_|=7u(9z%4Md>D`}1OmEOA+UTtjU^=Ds}ZFYDJ7$t6ew=AJw%KqH^p- zk7TQsv8#mQQguwPH6829OvaMb(|tbe|gwVFV+y!z$(Hwn>^Y!@qz%% zDct_zcoRW4eij#&-B=!p{#M(cE2}M5%LEY@Q`M_&@2C0n=a9Z^I?k?7E-XO*$(jK~ zI7n@+y0@y1bDn~`#dsRaG_w-62flF6-pC2(i8CvK@y)Dw2IwOp}7~ zmW{2e6sg)qu!!phTn~y^H)hpBm>+FR(zrNs(GGOav2muVyt-)T@~tckQR8bWCT=9> zUE<1yrd81LnkXTL9jMk?if^?lh@({N%MD%XI3)^+6m+%CI!3ceE^f4!;44}LeeSco z_7`bOw9HAuxr>WcZrVo8zTpo?Puk14+~YG%-ZS&Eo(EI7| z%1vKfU0qp2(@J(&+@9@{o6n(*^Nk4Z`tY@gb-sBw!S^CAx+>q1Xz-1R2H(3|A9R3 z0bP@-FqsC5wFWy+T3~5PetH-Ay!NVruZh(yH%_z4r~0boEfSt3)TI4HtMs9M*ZEuH za~tUFr28$W;x02v)%vYd@0`{2$Xn(oG!kekw5%DND~4XxzQhP~){jS^VDe-6FwUgH z7~J8ZRP)i8>bF8aO4nTG;xu!{G%@&u_KW0WJ=mBd?g;e+w`M0SO0RaSW0N+Ddc<0!?^6b+C$CG?@O{nksgfB=)Elk( z9ww$0a|Mw{gWeXEy1RW2E6j8UT2rf$&B*_dl!R}@gS zXQVm5wU!M7d>eL8XB#&j`xExosVO{Hj8+#(iAvw2*Fw6b+cOSS=V&Qv6pd7z`>^`Z z9#QHBuzmW*b^P9|(4XHMnyLB{t!PKM!jz45j=b}HK~>b~>C^2xPKg*&m3q*|@Gn|V zH~u&IJm=%|F1lB{1lsfTAd1sIt?)7VgH~@97*<#z(Z@QNcQ>D5FN{Nt6MWS3B>QBN z*fih2Il)JDmVsAH@ffwMhM&u{UW0l^Xrb}Yq{tE0JUzHuWB$>O)poZ&99nNvwkNh5 zaVNr9Nne6MdxDp2V%cp;eeJPiPIZIJ-ICr(BVpeOO4m~XAMVyV_|?kBHK{;N;vuSW zmumDJQkWZIt|Qj!Go&5>kDuUIv!H8AMn&H}54d~D;fu$Xqvr!|%<`6qf0U1?9&njH zt%26c6*Rt&|E6=dD5agMH4!~)&wNTFTgm;*TQunToAN0ci0z5@MG9~Of;x=R*V;kD zhisMNEG6I~O){TdhZrxF9{5n`;X{maM~L6yGQY-8iP+x*@WA8DXP&v<3*1}EZX0I~N$gErG4b~9b)`tW~lwO z!d$eAg>8>hVKQP>dD_?H-MTeTWn;ct|dK z(%r9vyLG$VfRSC|6(0MhecTy$bGwEhta;s1b*~V2pH6CSm6Gq-_V(@Pv;~$M%)Gsp z%nRi5Ucn_tz2+<}$nY_A2;8;JFQ?i-f3tLeZCZ3u)}?ijW_H$AO8W{awI`h;&7Qp5 zj<8PBAHAWYS!ow&m9+!i?Z3F(>yqyC zWZOuK_S%i7F<~j{!G3MMUMt82jrgp)Ls*hUgJ+L<9;c0H(aVz94^(=udS0M~C_CA+ zOWW4>xc9xf+q5S;TekM%#rD(OF<*h)u2M?)Z_k>e(blPS2?1g{na}@n5Z$;( zcl$Vfw=2L}9xZI5{<{a#>?ks=1w*mOL`xvz7y7;Wy0wp>?A<=iLPZrvqb6G>8NvOn zhv``gw>FcMcbT1aFrZ$v$dMSm@yhX{<%&=jZIdac4H=0`inS-1b`dTJI*C0|^#p6x zlsu_(Y%5dsM2dcEXsZWR@Ad@#ga}2ziCBVI8}0K~srt}dJr@1;JSc<)xVE!NFef|6CV9c<~b48oi?Ao|=c$tU&VHBGlqBlwvm z8`W>qPy@}Wy@sr?*q#kki29L9LCW?AZTn8_pkwqccOWC*;{7ku9z4s?cG4=j&ux`Z z?UGYkqp+8F!y*&cTDCg`-N74;5?OhN9=KP1H-Jj8h(*~vZr++3r2HQ35V0CB9}WJG zcIMr1w4T529>s?FB0mtKkni&nRxLbhA({j^V1*DZm=MWJ$glSdeUX(A?R?5T!cU4o zcRAVgC$PJ;s5(>K=V6R%CQS=zahyEFEg%r4r$TWYS%vg)gb zr6?E@QQ&*$x&&~|v9ex>NK{2<@B*z@n3*&ZzwYw0DlRUfJ)HJAL4)J+w_M==3Oc$3 zl(Z?WiiAZJJYHytwmZjmeX-QtcRy`CtM42s?YHvt5Kg>3C;zA0bA;B3-Zw+aEu8=o zFFrlx%QqbTZJoA~XiL^o(obUdX*F+DdI(DyZM86wa*DeH?R?d9El(rf56pW!Koe{e z+v{m>$}euOeO&|Zt@b^FPg-15NaPa{|M?J5w`}U0MUin0xN}E);}Gn`=vNYDgxoHq zRFCT9QFV0UpS+o$XU^kquE6UX9Ua7%i>Npn}`ATeQNW ze|bX_zI<0$6ZrFOo;u<#>%hn^`BFvQ!a4iwR(X*8-sq@%ASv^fxTkebu^qMh(&CURTCV7;n*j7BGh>SMPv=gPFvv#L~Xl~QHPuPSe zAeHv1dPW&f<&w!TxuqEXhz zF^A_qF>=|Hi9)2)O*#L)Th;C3!kyI+?zVLZefSXTqB=LK0b#ixy>)Ki_LesD{00rr+cTx+b^qMl-@CVT&}V-vQ`&rj-b zz4@-*p?o)8@_W7tvIISqY^MAH{2iHGC0iOVO_X~onM`TC$7QqSGGV4%?j@79Fm-(Qh(yrZ^u2ix( zv^&$CP7jy+)nK<(9#CZ;Ef!QU#D~jy1}F{E-=OO*-N&;u$guscD<=9}Hbe)k#-vr~ zvkHpS0p-LPu8YCcJkQ7$&F#(zT7ExB{i%paTddb*^wiufU&tZS!%RzqnteIUzHGAx z&hAV;PaePPpokEY&nvgTKjacoZa+V++@0y`3%Nv;+t;Vufq{@qM7aY4!uingq2uHW z7K>_O6zOw4nL?pJQI1-QX>gte73>}QJaG!aODhH9VqD{uH48N&qV%9ppfnMUKL`TU zbI2v4+(JPJP^P5}0fhmwY)G*W#NE0QS}dswy%L_qZ~l)gZH>rYXkMtSP0TzWKgrI@Lx;;F^v7 z+tz>c^`e3BegAmX9?f@r>Kp#?ZU6Y5f4p2Qj%Kp(ooj3l{Wa$DLD#ciSW^gM6wX`t zmW87h9=34G!bcQ>7}fl_#h>H3$qwl_P^u#e~5yfH4@M=sX0{Tbks5HOG`|@Bkyt`+8lbR4LW{qe@=31uE@penwn1h~lYR%5CXK0=$gr)V&8U5--O1krq1J4yMOG_H zgF*O=uSml7>MR4Oak*%lnWvaF`&2E%K2-Ej(=Dl!cEdWMin#&n^C>#oso3z%eui z977K{h8}PXJ>VF6z%ld?$1pG|mK4XZ8 z;WFBZ{%1+B1uL%DyvCRnHBA_-U8__~FvQ@TO{VQJD5 z@XKuJN-;c;BuW)Dg)3rmG*tNf$KUJ3JsJq|3M4m1K9J@i>5CeIctgPx00X^0-^~&} zW+V&+kB$M6qy$E<(%S(q;8ifqOWCX=KrBT`3N19nr}e4 zl)aJ9tJ4|Z>8UhllbjPGd03Bf>; z%OVIP>;+)|DFuokK>qfiOakUtj^Hc4}@%bHG9v<=ye0~^$6taX&^}$kk;Sp zrMNuG*7Ahx=5>REj*MLL+M5C^kMWf$2ST*5-WGipt@hiZls7H+U4!7=2*JB)2uLIl zyxW36*@B=Cy{@$JT)FHA-FU88Ech(sF#qxcA@ykK(N-J@&HZ^)3{?2M zLH4c@#dYZ@Oyj!7G=jJu#`Ls8%E-7?Br;}B8?V^fZMSi&Py4XFtL9=3oLW~U#Du%(9m8~ZpN_1c#MEd(fq^~bT@_8Z{WZDMemaE1g zSD8$H55(J7iNk0~KcL_)1shiRF|Od57TLTWW1IVdKMNO`1k*4zo?<@N%jE)H!MFJ* z2z}~#WROzg1;yfkYOsKQF7#r09E^&X7TiF4tZ#p7%n;k$-><#&Z?mP%CtxU4rxR96 zX#{nb?XRb`Ac!lG!RFJpfImnUP*E*lkp=AP^>NKVa8)+m<_igjZN!l2NibXo%%u6f7GM@#{HyeWG1y<7 zgYPr{dmc9=*QQs8-_+ujl|tHDD5}b{)Niuj%F(jFsXhEhPzHPdM+2hEATUi2Dcxr> zapSe2jXxGCYW+ou8{cprL1)?E7va%edb0$iPfw2@MDn@}e}DYhfq(h2&nfxUa{JXy~_WNJI^qH@A|M#yw`<(-8^`G_qtAG8QKYZxWpZ&d;{^2cq{@|PU{mI`i zoLm0WpZ)Mx-#vEyKb&{}qHD6N`a8G&FzJKtEPks1L4?gsty8h&czxVXVU)y)vOPbM8b2u+p z^rzQB=_tXuOtvrArCDw~m+kI{i4}6an0ytPeWm-d-8rZcpH>cfoE&N%AdOtMK6>`b z5hPYq=+0%)bEt|9Pl&;yaNfeVEF87)u!U0=KB5rKT{VAh@h2_*w#DDI_)8WZweXaM z6$>BSmvLpjZ&!(5NV&QWZe#63R z7XG${uPfaAzJ;$^&N~*jnw#IY`1dS)S)NpRH2QLA0~QnB&a+W#pfB&Tr8<1hRNy`6 zx0zCRtTuv+$(1k=NEMm-(=B zWv=y!iv#-1*nEW-^4EEP%;jlm99PrcX!gLJnqM~h`7#mfviW5UDa4Xwl{mK5dEBzf zGJ^8up7Av!zE%&BwE)A*e8)g9;Z*i&@p*cvd)CME%F4>c+krE-Va@bh(qX_0)E>r9ktY6RC<9VawE6^%lRVqAYxf{Ol3A$i5&l6&i zFhwj6nI>db_w%dSMn#Rv9G~=RRCu?#(y(t&rLe^LR+%5)_7z8X$BQ@W!V6t`W7JhL z?$%JqYf{@(_!WM}yREgoL2qqabj)k3*71aWKi#>GHoRD<57RT=u8ivs-SH+oBo9S3 zzv`J9sLg^j39|A)t~Z}&A+!csn*3010F?5loP{u(kC%oZ$|4f)SrvD&qO2<&VA8Se zkw@7~m+kw_H#~#+=C5Yl1nh+$WX={Cd*yQcE=gu4+c&w)OaFY4U_L`j)D8;)Ay3sd-n*K?Mt7a--!_E|J8?*~vOR!pb!AEo7l*rYw)uyU^{FL)bC;u&yEskFAz45SrZ5m=>-uCsq;xbo+I&Vb7=vS|`Nxut_GDH!Gx6rz z-W#F5Vm?ePlecBWt*r%_K_cU4*?7u7nwr%{GfOT`VH|g&s-~aQ+t%RS>@690Q+V~( z3s0meO!y8|EFr+WkNv=gBYkr}*dgpEH(;E@R$+X9c2BO~TRv=fSTJ&pLon8FI4^x{ zhJdXn>XT^eMQ{yM=cOZEy5%_Pc8U(=qq1f{QS^yy3G$L=vP1^ zX3D?={e51*uI>Uu*vh3Uq*0nQ>cIXMJ#0Q^dM6Zyku43>XbqclsQC)6PX3`(5%1F! z$!fk5$}BE*O#L>mQ(zUKI5W#NP9Cn&!*KR54~s#&A_2^(q+&!>56zI6%ys_7z2&7B z>x4e{sA#zPLPBxqhthpBOkj78MSh%rFbi#jtik$U6mERWAhsEZx@6x=JN!zn(v=_X z!C6UW|K8ldaL;g0sreWD!@~;SpqIY1wGYMb$!ITcKB4|I?1^k|m!a-yX(C;w+2BPI z{~m_MhH`~s7ZG?mR61Pb5WsaoeNrP4F2-s6E|XV4yBhq#O^plcNsVii$g@%`4sA-n zVC!pTiz<7ay(*k+{-jhXo1HZv&hQh?3pamax@z55vq73N_N|9E385R2X7iPTfAkN5 zLG)?QAdDwtpCQU_%D7!4BfrK!|J|JiAOCR046oYpi!tjXD|{Kt^=DjB}tv7m4<+FSgsZn`&q;jHm`9gi| z!d;c)^||xa+G6F%NM+{o%3YQ5#oCoxy)r&hd1!^7YF}@xT-vU`QN|q|tDHK|H-uIz zN7kzKb5uj6tk?(F8Wlbtre95(=aL_Sd!NmsQg2kM6+T4aznWB8S*WBY%NfmVA#5i5*B)N0uJTh;t?w7u7e^ZzH+65;>M2-OywXaxMZT1( zmlW{z$+e@4i^uuCga5t4T5V)rdO3go=k2a?*kU`u4hD8Gu!Dge4D4Xw{~iW1j+;O3 z1E>S-FnDJJFP(JctKNhBf8=o1z0|Fg|MOD!JwzUI)9wu61TW`L^K!yTUOG9$^MpG_ zTz|gX{h$Ab+(5nf0sidnuGaI{trV|1&qVtA%%eOq^s1}f$G9=88^pTRq#L~Y^AT&M zV+vi>=4QKdw8t&do} z8EUOq`8c_H4MH#3RQR-jdU=R4UCb8_^@71Aa^D|(qhY?IHs4c>E6UXRYGh$s*z>(< zWI=S=@`O>%!{5r$YWvSmpxaXGLv3r}sah`t>eUF%6!$ZK5}MPUa({PTchfa)y0(8E zP1w?_Pr7|RVlx(vo-+D5NgF|`*B!L_k!D-3p}cQ8x{KYMp;zH^9@^7e$lLD|=MEXo zx7XcD`8T5b!`613S?eaeUc&LOB);GFhQOU*2Ln48*ulUK26iy8gMl3k>|kIA1OGo@ zU^I*NjA76B6nFmYU|FtCGx9SrPXU + + + nunit.framework + + + +

+ The different targets a test action attribute can be applied to + + + + + Default target, which is determined by where the action attribute is attached + + + + + Target a individual test case + + + + + Target a suite of test cases + + + + + Delegate used by tests that execute code and + capture any thrown exception. + + + + + The Assert class contains a collection of static methods that + implement the most common assertions used in NUnit. + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + The message to initialize the with. + + + + Throws a with the message and arguments + that are passed in. This allows a test to be cut short, with a result + of success returned to NUnit. + + + + + Throws an with the message and arguments + that are passed in. This is used by the other Assert functions. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This is used by the other Assert functions. + + The message to initialize the with. + + + + Throws an . + This is used by the other Assert functions. + + + + + Throws an with the message and arguments + that are passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This causes the test to be reported as ignored. + + The message to initialize the with. + + + + Throws an . + This causes the test to be reported as ignored. + + + + + Throws an with the message and arguments + that are passed in. This causes the test to be reported as inconclusive. + + The message to initialize the with. + Arguments to be used in formatting the message + + + + Throws an with the message that is + passed in. This causes the test to be reported as inconclusive. + + The message to initialize the with. + + + + Throws an . + This causes the test to be reported as Inconclusive. + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + Used as a synonym for That in rare cases where a private setter + causes a Visual Basic compilation error. + + + This method is provided for use by VB developers needing to test + the value of properties with private setters. + + The actual value to test + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + A constraint to be satisfied by the exception + A TestDelegate + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + The exception Type expected + A TestDelegate + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws a particular exception when called. + + Type of the expected exception + A TestDelegate + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception when called + and returns it. + + A TestDelegate + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate throws an exception of a certain Type + or one derived from it when called and returns it. + + The expected Exception Type + A TestDelegate + + + + Verifies that a delegate does not throw an exception + + A TestDelegate + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Verifies that a delegate does not throw an exception. + + A TestDelegate + The message that will be displayed on failure + + + + Verifies that a delegate does not throw an exception. + + A TestDelegate + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + The message to display in case of failure + + + + Asserts that a condition is false. If the condition is true the method throws + an . + + The evaluated condition + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is not equal to null + If the object is null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + The message to display in case of failure + + + + Verifies that the object that is passed in is equal to null + If the object is not null then an + is thrown. + + The object that is to be tested + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned ints are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned longs are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two decimals are equal. If they are not, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + + + + Verifies that two doubles are equal considering a delta. If the + expected value is infinity then the delta value is ignored. If + they are not equal then an is + thrown. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + + + + Verifies that two objects are equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are not equal an is thrown. + + The value that is expected + The actual value + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned ints are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two unsigned longs are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two decimals are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two floats are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + The message to display in case of failure + + + + Verifies that two doubles are not equal. If they are equal, then an + is thrown. + + The expected value + The actual value + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + The message to display in case of failure + + + + Verifies that two objects are not equal. Two objects are considered + equal if both are null, or if both have the same value. NUnit + has special semantics for some object types. + If they are equal an is thrown. + + The value that is expected + The actual value + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + + + + Asserts that two objects refer to the same object. If they + are not the same an is thrown. + + The expected object + The actual object + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + The message to display in case of failure + + + + Asserts that two objects do not refer to the same object. If they + are the same an is thrown. + + The expected object + The actual object + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + The message to display in case of failure + + + + Verifies that the double that is passed in is an NaN value. + If the object is not NaN then an + is thrown. + + The value that is to be tested + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is empty - that is equal to string.Empty + + The string to be tested + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing ICollection + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is not empty - that is not equal to string.Empty + + The string to be tested + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + The message to display in case of failure + + + + Assert that an array, list or other collection is not empty + + An array, list or other collection implementing ICollection + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is either null or equal to string.Empty + + The string to be tested + + + + Assert that a string is not null or empty + + The string to be tested + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Assert that a string is not null or empty + + The string to be tested + The message to display in case of failure + + + + Assert that a string is not null or empty + + The string to be tested + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + The message to display in case of failure + + + + Asserts that an object may not be assigned a value of a given Type. + + The expected Type. + The object under examination + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + The message to display in case of failure + + + + Asserts that an object is not an instance of a given type. + + The expected Type + The object being examined + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than the second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + The message to display in case of failure + + + + Verifies that the first value is greater than or equal tothe second + value. If it is not, then an + is thrown. + + The first value, expected to be greater + The second value, expected to be less + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + The message to display in case of failure + + + + Verifies that the first value is less than or equal to the second + value. If it is not, then an + is thrown. + + The first value, expected to be less + The second value, expected to be greater + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + The message to display in case of failure + + + + Asserts that an object is contained in a list. + + The expected object + The list to be examined + + + + Helper for Assert.AreEqual(double expected, double actual, ...) + allowing code generation to work consistently. + + The expected value + The actual value + The maximum acceptable difference between the + the expected and the actual + The message to display in case of failure + Array of objects to be used in formatting the message + + + + Gets the number of assertions executed so far and + resets the counter to zero. + + + + + AssertionHelper is an optional base class for user tests, + allowing the use of shorter names for constraints and + asserts and avoiding conflict with the definition of + , from which it inherits much of its + behavior, in certain mock object frameworks. + + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new ContainsConstraint. This constraint + will, in turn, make use of the appropriate second-level + constraint, depending on the type of the actual argument. + This overload is only used if the item sought is a string, + since any other type implies that we are looking for a + collection member. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that fails if the actual + value matches the pattern supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + The message to be displayed in case of failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. Works + identically to Assert.That. + + The actual value to test + A Constraint to be applied + The message to be displayed in case of failure + Arguments to use in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to + . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the method throws + an . Works Identically to . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an assertion exception on failure. + + The actual value to test + A Constraint to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Returns a ListMapper based on a collection. + + The original collection + + + + + Provides static methods to express the assumptions + that must be met for a test to give a meaningful + result. If an assumption is not met, the test + should produce an inconclusive result. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + Arguments to be used in formatting the message + + + + Asserts that a condition is true. If the condition is false the method throws + an . + + The evaluated condition + The message to display if the condition is false + + + + Asserts that a condition is true. If the condition is false the + method throws an . + + The evaluated condition + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + An ActualValueDelegate returning the value to be tested + The message that will be displayed on failure + + + + Apply a constraint to an actual value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + An ActualValueDelegate returning the value to be tested + A Constraint expression to be applied + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + + + + Apply a constraint to a referenced value, succeeding if the constraint + is satisfied and throwing an InconclusiveException on failure. + + A Constraint expression to be applied + The actual value to test + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that the code represented by a delegate throws an exception + that satisfies the constraint provided. + + A TestDelegate to be executed + A ThrowsConstraint used in the test + + + + Waits for pending asynchronous operations to complete, if appropriate, + and returns a proper result of the invocation by unwrapping task results + + The raw result of the method invocation + The unwrapped result, if necessary + + + + A set of Assert methods operationg on one or more collections + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + + + + Asserts that all items contained in collection are of the type specified by expectedType. + + IEnumerable containing objects to be considered + System.Type that all objects in collection must be instances of + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable containing objects to be considered + The message that will be displayed on failure + + + + Asserts that all items contained in collection are not equal to null. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Ensures that every object contained in collection exists within the collection + once and only once. + + IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are exactly equal. The collections must have the same count, + and contain the exact same objects in the same order. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are equivalent, containing the same objects but the match may be in any order. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + + + + Asserts that expected and actual are not exactly equal. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not exactly equal. + If comparer is not null then it will be used to compare the objects. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The IComparer to use in comparing objects from each IEnumerable + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + + + + Asserts that expected and actual are not equivalent. + + The first IEnumerable of objects to be considered + The second IEnumerable of objects to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + + + + Asserts that collection contains actual as an item. + + IEnumerable of objects to be considered + Object to be found within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + + + + Asserts that collection does not contain actual as an item. + + IEnumerable of objects to be considered + Object that cannot exist within collection + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that superset is not a subject of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + + + + Asserts that superset is not a subject of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + + + + Asserts that superset is not a subject of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Asserts that superset is a subset of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + + + + Asserts that superset is a subset of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + + + + Asserts that superset is a subset of subset. + + The IEnumerable superset to be considered + The IEnumerable subset to be considered + The message that will be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is empty + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array,list or other collection is empty + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + The message to be displayed on failure + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + The message to be displayed on failure + Arguments to be used in formatting the message + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + The message to be displayed on failure + + + + Assert that an array, list or other collection is ordered + + An array, list or other collection implementing IEnumerable + A custom comparer to perform the comparisons + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Summary description for DirectoryAssert + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are not equal + + + + Verifies that two directories are equal. Two directories are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + The message to display if directories are not equal + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory containing the value that is expected + A directory containing the actual value + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are equal + Arguments to be used in formatting the message + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + The message to display if directories are equal + + + + Asserts that two directories are not equal. If they are equal + an is thrown. + + A directory path string containing the value that is expected + A directory path string containing the actual value + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is empty. If it is not empty + an is thrown. + + A directory to search + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + Arguments to be used in formatting the message + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + The message to display if directories are not equal + + + + Asserts that the directory is not empty. If it is empty + an is thrown. + + A directory to search + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path contains actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + Arguments to be used in formatting the message + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + The message to display if directory is not within the path + + + + Asserts that path does not contain actual as a subdirectory or + an is thrown. + + A directory to search + sub-directory asserted to exist under directory + + + + Summary description for FileAssert. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + We don't actually want any instances of this object, but some people + like to inherit from it to add other static methods. Hence, the + protected constructor disallows any instances of this object. + + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + The message to display if objects are not equal + + + + Verifies that two Streams are equal. Two Streams are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The expected Stream + The actual Stream + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Verifies that two files are equal. Two files are considered + equal if both are null, or if both have the same value byte for byte. + If they are not equal an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the two Stream are the same. + Arguments to be used in formatting the message + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + The message to be displayed when the Streams are the same. + + + + Asserts that two Streams are not equal. If they are equal + an is thrown. + + The expected Stream + The actual Stream + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + A file containing the value that is expected + A file containing the actual value + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if Streams are not equal + Arguments to be used in formatting the message + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + The message to display if objects are not equal + + + + Asserts that two files are not equal. If they are equal + an is thrown. + + The path to a file containing the value that is expected + The path to a file containing the actual value + + + + GlobalSettings is a place for setting default values used + by the framework in performing asserts. + + + + + Default tolerance for floating point equality + + + + + Class used to guard against unexpected argument values + by throwing an appropriate exception. + + + + + Throws an exception if an argument is null + + The value to be tested + The name of the argument + + + + Throws an exception if a string argument is null or empty + + The value to be tested + The name of the argument + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + Interface implemented by a user fixture in order to + validate any expected exceptions. It is only called + for test methods marked with the ExpectedException + attribute. + + + + + Method to handle an expected exception + + The exception to be handled + + + + Helper class with properties and methods that supply + a number of constraints used in Asserts. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + The ITestCaseData interface is implemented by a class + that is able to return complete testcases for use by + a parameterized test method. + + NOTE: This interface is used in both the framework + and the core, even though that results in two different + types. However, sharing the source code guarantees that + the various implementations will be compatible and that + the core is able to reflect successfully over the + framework implementations of ITestCaseData. + + + + + Gets the argument list to be provided to the test + + + + + Gets the expected result + + + + + Indicates whether a result has been specified. + This is necessary because the result may be + null, so it's value cannot be checked. + + + + + Gets the expected exception Type + + + + + Gets the FullName of the expected exception + + + + + Gets the name to be used for the test + + + + + Gets the description of the test + + + + + Gets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets a value indicating whether this is explicit. + + true if explicit; otherwise, false. + + + + Gets the ignore reason. + + The ignore reason. + + + + The Iz class is a synonym for Is intended for use in VB, + which regards Is as a keyword. + + + + + The List class is a helper class with properties and methods + that supply a number of constraints used with lists and collections. + + + + + List.Map returns a ListMapper, which can be used to map + the original collection to another collection. + + + + + + + ListMapper is used to transform a collection used as an actual argument + producing another collection to be used in the assertion. + + + + + Construct a ListMapper based on a collection + + The collection to be transformed + + + + Produces a collection containing all the values of a property + + The collection of property values + + + + + Randomizer returns a set of random values in a repeatable + way, to allow re-running of tests if necessary. + + + + + Get a randomizer for a particular member, returning + one that has already been created if it exists. + This ensures that the same values are generated + each time the tests are reloaded. + + + + + Get a randomizer for a particular parameter, returning + one that has already been created if it exists. + This ensures that the same values are generated + each time the tests are reloaded. + + + + + Construct a randomizer using a random seed + + + + + Construct a randomizer using a specified seed + + + + + Return an array of random doubles between 0.0 and 1.0. + + + + + + + Return an array of random doubles with values in a specified range. + + + + + Return an array of random ints with values in a specified range. + + + + + Get a random seed for use in creating a randomizer. + + + + + The SpecialValue enum is used to represent TestCase arguments + that cannot be used as arguments to an Attribute. + + + + + Null represents a null value, which cannot be used as an + argument to an attribute under .NET 1.x + + + + + Basic Asserts on strings. + + + + + The Equals method throws an AssertionException. This is done + to make sure there is no mistake by calling this function. + + + + + + + override the default ReferenceEquals to throw an AssertionException. This + implementation makes sure there is no mistake in calling this function + as part of Assert. + + + + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + + + + Asserts that a string is not found within another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string is found within another string. + + The expected string + The string to be examined + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string starts with another string. + + The expected string + The string to be examined + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string does not start with another string. + + The expected string + The string to be examined + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string ends with another string. + + The expected string + The string to be examined + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + The message to display in case of failure + + + + Asserts that a string does not end with another string. + + The expected string + The string to be examined + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + + + + Asserts that two strings are equal, without regard to case. + + The expected string + The actual string + + + + Asserts that two strings are not equal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that two strings are Notequal, without regard to case. + + The expected string + The actual string + The message to display in case of failure + + + + Asserts that two strings are not equal, without regard to case. + + The expected string + The actual string + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + The message to display in case of failure + + + + Asserts that a string matches an expected regular expression pattern. + + The regex pattern to be matched + The actual string + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + The message to display in case of failure + Arguments used in formatting the message + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + The message to display in case of failure + + + + Asserts that a string does not match an expected regular expression pattern. + + The regex pattern to be used + The actual string + + + + The TestCaseData class represents a set of arguments + and other parameter info to be used for a parameterized + test case. It provides a number of instance modifiers + for use in initializing the test case. + + Note: Instance modifiers are getters that return + the same instance after modifying it's state. + + + + + The argument list to be provided to the test + + + + + The expected result to be returned + + + + + Set to true if this has an expected result + + + + + The expected exception Type + + + + + The FullName of the expected exception + + + + + The name to be used for the test + + + + + The description of the test + + + + + A dictionary of properties, used to add information + to tests without requiring the class to change. + + + + + If true, indicates that the test case is to be ignored + + + + + If true, indicates that the test case is marked explicit + + + + + The reason for ignoring a test case + + + + + Initializes a new instance of the class. + + The arguments. + + + + Initializes a new instance of the class. + + The argument. + + + + Initializes a new instance of the class. + + The first argument. + The second argument. + + + + Initializes a new instance of the class. + + The first argument. + The second argument. + The third argument. + + + + Sets the expected result for the test + + The expected result + A modified TestCaseData + + + + Sets the expected exception type for the test + + Type of the expected exception. + The modified TestCaseData instance + + + + Sets the expected exception type for the test + + FullName of the expected exception. + The modified TestCaseData instance + + + + Sets the name of the test case + + The modified TestCaseData instance + + + + Sets the description for the test case + being constructed. + + The description. + The modified TestCaseData instance. + + + + Applies a category to the test + + + + + + + Applies a named property to the test + + + + + + + + Applies a named property to the test + + + + + + + + Applies a named property to the test + + + + + + + + Ignores this TestCase. + + + + + + Ignores this TestCase, specifying the reason. + + The reason. + + + + + Marks this TestCase as Explicit + + + + + + Marks this TestCase as Explicit, specifying the reason. + + The reason. + + + + + Gets the argument list to be provided to the test + + + + + Gets the expected result + + + + + Returns true if the result has been set + + + + + Gets the expected exception Type + + + + + Gets the FullName of the expected exception + + + + + Gets the name to be used for the test + + + + + Gets the description of the test + + + + + Gets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets a value indicating whether this is explicit. + + true if explicit; otherwise, false. + + + + Gets the ignore reason. + + The ignore reason. + + + + Gets a list of categories associated with this test. + + + + + Gets the property dictionary for this test + + + + + Provide the context information of the current test + + + + + Constructs a TestContext using the provided context dictionary + + A context dictionary + + + + Get the current test context. This is created + as needed. The user may save the context for + use within a test, but it should not be used + outside the test for which it is created. + + + + + Gets a TestAdapter representing the currently executing test in this context. + + + + + Gets a ResultAdapter representing the current result for the test + executing in this context. + + + + + Gets the directory containing the current test assembly. + + + + + Gets the directory to be used for outputing files created + by this test run. + + + + + TestAdapter adapts a Test for consumption by + the user test code. + + + + + Constructs a TestAdapter for this context + + The context dictionary + + + + The name of the test. + + + + + The FullName of the test + + + + + The properties of the test. + + + + + ResultAdapter adapts a TestResult for consumption by + the user test code. + + + + + Construct a ResultAdapter for a context + + The context holding the result + + + + The TestState of current test. This maps to the ResultState + used in nunit.core and is subject to change in the future. + + + + + The TestStatus of current test. This enum will be used + in future versions of NUnit and so is to be preferred + to the TestState value. + + + + + Provides details about a test + + + + + Creates an instance of TestDetails + + The fixture that the test is a member of, if available. + The method that implements the test, if available. + The full name of the test. + A string representing the type of test, e.g. "Test Case". + Indicates if the test represents a suite of tests. + + + + The fixture that the test is a member of, if available. + + + + + The method that implements the test, if available. + + + + + The full name of the test. + + + + + A string representing the type of test, e.g. "Test Case". + + + + + Indicates if the test represents a suite of tests. + + + + + The ResultState enum indicates the result of running a test + + + + + The result is inconclusive + + + + + The test was not runnable. + + + + + The test has been skipped. + + + + + The test has been ignored. + + + + + The test succeeded + + + + + The test failed + + + + + The test encountered an unexpected exception + + + + + The test was cancelled by the user + + + + + The TestStatus enum indicates the result of running a test + + + + + The test was inconclusive + + + + + The test has skipped + + + + + The test succeeded + + + + + The test failed + + + + + Helper class with static methods used to supply constraints + that operate on strings. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that fails if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the Regex pattern supplied as an argument. + + + + + Returns a constraint that fails if the actual + value matches the pattern supplied as an argument. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + TextMessageWriter writes constraint descriptions and messages + in displayable form as a text stream. It tailors the display + of individual message components to form the standard message + format of NUnit assertion failure messages. + + + + + MessageWriter is the abstract base for classes that write + constraint descriptions and messages in some form. The + class has separate methods for writing various components + of a message, allowing implementations to tailor the + presentation as needed. + + + + + Construct a MessageWriter given a culture + + + + + Method to write single line message with optional args, usually + written to precede the general failure message. + + The message to be written + Any arguments used in formatting the message + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the Expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in locating the point where the strings differ + If true, the strings should be clipped to fit the line + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for a modifier + + The modifier. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Abstract method to get the max line length + + + + + Prefix used for the expected value line of a message + + + + + Prefix used for the actual value line of a message + + + + + Length of a message prefix + + + + + Construct a TextMessageWriter + + + + + Construct a TextMessageWriter, specifying a user message + and optional formatting arguments. + + + + + + + Method to write single line message with optional args, usually + written to precede the general failure message, at a givel + indentation level. + + The indentation level of the message + The message to be written + Any arguments used in formatting the message + + + + Display Expected and Actual lines for a constraint. This + is called by MessageWriter's default implementation of + WriteMessageTo and provides the generic two-line display. + + The constraint that failed + + + + Display Expected and Actual lines for given values. This + method may be called by constraints that need more control over + the display of actual and expected values than is provided + by the default implementation. + + The expected value + The actual value causing the failure + + + + Display Expected and Actual lines for given values, including + a tolerance value on the expected line. + + The expected value + The actual value causing the failure + The tolerance within which the test was made + + + + Display the expected and actual string values on separate lines. + If the mismatch parameter is >=0, an additional line is displayed + line containing a caret that points to the mismatch point. + + The expected string value + The actual string value + The point at which the strings don't match or -1 + If true, case is ignored in string comparisons + If true, clip the strings to fit the max line length + + + + Writes the text for a connector. + + The connector. + + + + Writes the text for a predicate. + + The predicate. + + + + Write the text for a modifier. + + The modifier. + + + + Writes the text for an expected value. + + The expected value. + + + + Writes the text for an actual value. + + The actual value. + + + + Writes the text for a generalized value. + + The value. + + + + Writes the text for a collection value, + starting at a particular point, to a max length + + The collection containing elements to write. + The starting point of the elements to write + The maximum number of elements to write + + + + Write the generic 'Expected' line for a constraint + + The constraint that failed + + + + Write the generic 'Expected' line for a given value + + The expected value + + + + Write the generic 'Expected' line for a given value + and tolerance. + + The expected value + The tolerance within which the test was made + + + + Write the generic 'Actual' line for a constraint + + The constraint for which the actual value is to be written + + + + Write the generic 'Actual' line for a given value + + The actual value causing a failure + + + + Gets or sets the maximum line length for this writer + + + + + Helper class with properties and methods that supply + constraints that operate on exceptions. + + + + + Creates a constraint specifying the exact type of exception expected + + + + + Creates a constraint specifying the exact type of exception expected + + + + + Creates a constraint specifying the type of exception expected + + + + + Creates a constraint specifying the type of exception expected + + + + + Creates a constraint specifying an expected exception + + + + + Creates a constraint specifying an exception with a given InnerException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying an expected TargetInvocationException + + + + + Creates a constraint specifying that no exception is thrown + + + + + Attribute used to apply a category to a test + + + + + The name of the category + + + + + Construct attribute for a given category based on + a name. The name may not contain the characters ',', + '+', '-' or '!'. However, this is not checked in the + constructor since it would cause an error to arise at + as the test was loaded without giving a clear indication + of where the problem is located. The error is handled + in NUnitFramework.cs by marking the test as not + runnable. + + The name of the category + + + + Protected constructor uses the Type name as the name + of the category. + + + + + The name of the category + + + + + Used to mark a field for use as a datapoint when executing a theory + within the same fixture that requires an argument of the field's Type. + + + + + Used to mark an array as containing a set of datapoints to be used + executing a theory within the same fixture that requires an argument + of the Type of the array elements. + + + + + Attribute used to provide descriptive text about a + test case or fixture. + + + + + Construct the attribute + + Text describing the test + + + + Gets the test description + + + + + Enumeration indicating how the expected message parameter is to be used + + + + Expect an exact match + + + Expect a message containing the parameter string + + + Match the regular expression provided as a parameter + + + Expect a message that starts with the parameter string + + + + ExpectedExceptionAttribute + + + + + + Constructor for a non-specific exception + + + + + Constructor for a given type of exception + + The type of the expected exception + + + + Constructor for a given exception name + + The full name of the expected exception + + + + Gets or sets the expected exception type + + + + + Gets or sets the full Type name of the expected exception + + + + + Gets or sets the expected message text + + + + + Gets or sets the user message displayed in case of failure + + + + + Gets or sets the type of match to be performed on the expected message + + + + + Gets the name of a method to be used as an exception handler + + + + + ExplicitAttribute marks a test or test fixture so that it will + only be run if explicitly executed from the gui or command line + or if it is included by use of a filter. The test will not be + run simply because an enclosing suite is run. + + + + + Default constructor + + + + + Constructor with a reason + + The reason test is marked explicit + + + + The reason test is marked explicit + + + + + Attribute used to mark a test that is to be ignored. + Ignored tests result in a warning message when the + tests are run. + + + + + Constructs the attribute without giving a reason + for ignoring the test. + + + + + Constructs the attribute giving a reason for ignoring the test + + The reason for ignoring the test + + + + The reason for ignoring a test + + + + + Abstract base for Attributes that are used to include tests + in the test run based on environmental settings. + + + + + Constructor with no included items specified, for use + with named property syntax. + + + + + Constructor taking one or more included items + + Comma-delimited list of included items + + + + Name of the item that is needed in order for + a test to run. Multiple itemss may be given, + separated by a comma. + + + + + Name of the item to be excluded. Multiple items + may be given, separated by a comma. + + + + + The reason for including or excluding the test + + + + + PlatformAttribute is used to mark a test fixture or an + individual method as applying to a particular platform only. + + + + + Constructor with no platforms specified, for use + with named property syntax. + + + + + Constructor taking one or more platforms + + Comma-deliminted list of platforms + + + + CultureAttribute is used to mark a test fixture or an + individual method as applying to a particular Culture only. + + + + + Constructor with no cultures specified, for use + with named property syntax. + + + + + Constructor taking one or more cultures + + Comma-deliminted list of cultures + + + + Marks a test to use a combinatorial join of any argument data + provided. NUnit will create a test case for every combination of + the arguments provided. This can result in a large number of test + cases and so should be used judiciously. This is the default join + type, so the attribute need not be used except as documentation. + + + + + PropertyAttribute is used to attach information to a test as a name/value pair.. + + + + + Construct a PropertyAttribute with a name and string value + + The name of the property + The property value + + + + Construct a PropertyAttribute with a name and int value + + The name of the property + The property value + + + + Construct a PropertyAttribute with a name and double value + + The name of the property + The property value + + + + Constructor for derived classes that set the + property dictionary directly. + + + + + Constructor for use by derived classes that use the + name of the type as the property name. Derived classes + must ensure that the Type of the property value is + a standard type supported by the BCL. Any custom + types will cause a serialization Exception when + in the client. + + + + + Gets the property dictionary for this attribute + + + + + Default constructor + + + + + Marks a test to use pairwise join of any argument data provided. + NUnit will attempt too excercise every pair of argument values at + least once, using as small a number of test cases as it can. With + only two arguments, this is the same as a combinatorial join. + + + + + Default constructor + + + + + Marks a test to use a sequential join of any argument data + provided. NUnit will use arguements for each parameter in + sequence, generating test cases up to the largest number + of argument values provided and using null for any arguments + for which it runs out of values. Normally, this should be + used with the same number of arguments for each parameter. + + + + + Default constructor + + + + + Summary description for MaxTimeAttribute. + + + + + Construct a MaxTimeAttribute, given a time in milliseconds. + + The maximum elapsed time in milliseconds + + + + RandomAttribute is used to supply a set of random values + to a single parameter of a parameterized test. + + + + + ValuesAttribute is used to provide literal arguments for + an individual parameter of a test. + + + + + Abstract base class for attributes that apply to parameters + and supply data for the parameter. + + + + + Gets the data to be provided to the specified parameter + + + + + The collection of data to be returned. Must + be set by any derived attribute classes. + We use an object[] so that the individual + elements may have their type changed in GetData + if necessary. + + + + + Construct with one argument + + + + + + Construct with two arguments + + + + + + + Construct with three arguments + + + + + + + + Construct with an array of arguments + + + + + + Get the collection of values to be used as arguments + + + + + Construct a set of doubles from 0.0 to 1.0, + specifying only the count. + + + + + + Construct a set of doubles from min to max + + + + + + + + Construct a set of ints from min to max + + + + + + + + Get the collection of values to be used as arguments + + + + + RangeAttribute is used to supply a range of values to an + individual parameter of a parameterized test. + + + + + Construct a range of ints using default step of 1 + + + + + + + Construct a range of ints specifying the step size + + + + + + + + Construct a range of longs + + + + + + + + Construct a range of doubles + + + + + + + + Construct a range of floats + + + + + + + + RepeatAttribute may be applied to test case in order + to run it multiple times. + + + + + Construct a RepeatAttribute + + The number of times to run the test + + + + RequiredAddinAttribute may be used to indicate the names of any addins + that must be present in order to run some or all of the tests in an + assembly. If the addin is not loaded, the entire assembly is marked + as NotRunnable. + + + + + Initializes a new instance of the class. + + The required addin. + + + + Gets the name of required addin. + + The required addin name. + + + + Summary description for SetCultureAttribute. + + + + + Construct given the name of a culture + + + + + + Summary description for SetUICultureAttribute. + + + + + Construct given the name of a culture + + + + + + SetUpAttribute is used in a TestFixture to identify a method + that is called immediately before each test is run. It is + also used in a SetUpFixture to identify the method that is + called once, before any of the subordinate tests are run. + + + + + Attribute used to mark a class that contains one-time SetUp + and/or TearDown methods that apply to all the tests in a + namespace or an assembly. + + + + + Attribute used to mark a static (shared in VB) property + that returns a list of tests. + + + + + Attribute used in a TestFixture to identify a method that is + called immediately after each test is run. It is also used + in a SetUpFixture to identify the method that is called once, + after all subordinate tests have run. In either case, the method + is guaranteed to be called, even if an exception is thrown. + + + + + Provide actions to execute before and after tests. + + + + + When implemented by an attribute, this interface implemented to provide actions to execute before and after tests. + + + + + Executed before each test is run + + Provides details about the test that is going to be run. + + + + Executed after each test is run + + Provides details about the test that has just been run. + + + + Provides the target for the action attribute + + The target for the action attribute + + + + Adding this attribute to a method within a + class makes the method callable from the NUnit test runner. There is a property + called Description which is optional which you can provide a more detailed test + description. This class cannot be inherited. + + + + [TestFixture] + public class Fixture + { + [Test] + public void MethodToTest() + {} + + [Test(Description = "more detailed description")] + publc void TestDescriptionMethod() + {} + } + + + + + + Descriptive text for this test + + + + + TestCaseAttribute is used to mark parameterized test cases + and provide them with their arguments. + + + + + Construct a TestCaseAttribute with a list of arguments. + This constructor is not CLS-Compliant + + + + + + Construct a TestCaseAttribute with a single argument + + + + + + Construct a TestCaseAttribute with a two arguments + + + + + + + Construct a TestCaseAttribute with a three arguments + + + + + + + + Gets the list of arguments to a test case + + + + + Gets or sets the expected result. Use + ExpectedResult by preference. + + The result. + + + + Gets or sets the expected result. + + The result. + + + + Gets a flag indicating whether an expected + result has been set. + + + + + Gets a list of categories associated with this test; + + + + + Gets or sets the category associated with this test. + May be a single category or a comma-separated list. + + + + + Gets or sets the expected exception. + + The expected exception. + + + + Gets or sets the name the expected exception. + + The expected name of the exception. + + + + Gets or sets the expected message of the expected exception + + The expected message of the exception. + + + + Gets or sets the type of match to be performed on the expected message + + + + + Gets or sets the description. + + The description. + + + + Gets or sets the name of the test. + + The name of the test. + + + + Gets or sets the ignored status of the test + + + + + Gets or sets the ignored status of the test + + + + + Gets or sets the explicit status of the test + + + + + Gets or sets the reason for not running the test + + + + + Gets or sets the reason for not running the test. + Set has the side effect of marking the test as ignored. + + The ignore reason. + + + + FactoryAttribute indicates the source to be used to + provide test cases for a test method. + + + + + Construct with the name of the data source, which must + be a property, field or method of the test class itself. + + An array of the names of the factories that will provide data + + + + Construct with a Type, which must implement IEnumerable + + The Type that will provide data + + + + Construct with a Type and name. + that don't support params arrays. + + The Type that will provide data + The name of the method, property or field that will provide data + + + + The name of a the method, property or fiend to be used as a source + + + + + A Type to be used as a source + + + + + Gets or sets the category associated with this test. + May be a single category or a comma-separated list. + + + + + [TestFixture] + public class ExampleClass + {} + + + + + Default constructor + + + + + Construct with a object[] representing a set of arguments. + In .NET 2.0, the arguments may later be separated into + type arguments and constructor arguments. + + + + + + Descriptive text for this fixture + + + + + Gets and sets the category for this fixture. + May be a comma-separated list of categories. + + + + + Gets a list of categories for this fixture + + + + + The arguments originally provided to the attribute + + + + + Gets or sets a value indicating whether this should be ignored. + + true if ignore; otherwise, false. + + + + Gets or sets the ignore reason. May set Ignored as a side effect. + + The ignore reason. + + + + Get or set the type arguments. If not set + explicitly, any leading arguments that are + Types are taken as type arguments. + + + + + Attribute used to identify a method that is + called before any tests in a fixture are run. + + + + + Attribute used to identify a method that is called after + all the tests in a fixture have run. The method is + guaranteed to be called, even if an exception is thrown. + + + + + Adding this attribute to a method within a + class makes the method callable from the NUnit test runner. There is a property + called Description which is optional which you can provide a more detailed test + description. This class cannot be inherited. + + + + [TestFixture] + public class Fixture + { + [Test] + public void MethodToTest() + {} + + [Test(Description = "more detailed description")] + publc void TestDescriptionMethod() + {} + } + + + + + + Used on a method, marks the test with a timeout value in milliseconds. + The test will be run in a separate thread and is cancelled if the timeout + is exceeded. Used on a method or assembly, sets the default timeout + for all contained test methods. + + + + + Construct a TimeoutAttribute given a time in milliseconds + + The timeout value in milliseconds + + + + Marks a test that must run in the STA, causing it + to run in a separate thread if necessary. + + On methods, you may also use STAThreadAttribute + to serve the same purpose. + + + + + Construct a RequiresSTAAttribute + + + + + Marks a test that must run in the MTA, causing it + to run in a separate thread if necessary. + + On methods, you may also use MTAThreadAttribute + to serve the same purpose. + + + + + Construct a RequiresMTAAttribute + + + + + Marks a test that must run on a separate thread. + + + + + Construct a RequiresThreadAttribute + + + + + Construct a RequiresThreadAttribute, specifying the apartment + + + + + ValueSourceAttribute indicates the source to be used to + provide data for one parameter of a test method. + + + + + Construct with the name of the factory - for use with languages + that don't support params arrays. + + The name of the data source to be used + + + + Construct with a Type and name - for use with languages + that don't support params arrays. + + The Type that will provide data + The name of the method, property or field that will provide data + + + + The name of a the method, property or fiend to be used as a source + + + + + A Type to be used as a source + + + + + AllItemsConstraint applies another constraint to each + item in a collection, succeeding if they all succeed. + + + + + Abstract base class used for prefixes + + + + + The Constraint class is the base of all built-in constraints + within NUnit. It provides the operator overloads used to combine + constraints. + + + + + The IConstraintExpression interface is implemented by all + complete and resolvable constraints and expressions. + + + + + Return the top-level constraint for this expression + + + + + + Static UnsetObject used to detect derived constraints + failing to set the actual value. + + + + + The actual value being tested against a constraint + + + + + The display name of this Constraint for use by ToString() + + + + + Argument fields used by ToString(); + + + + + The builder holding this constraint + + + + + Construct a constraint with no arguments + + + + + Construct a constraint with one argument + + + + + Construct a constraint with two arguments + + + + + Sets the ConstraintBuilder holding this constraint + + + + + Write the failure message to the MessageWriter provided + as an argument. The default implementation simply passes + the constraint and the actual value to the writer, which + then displays the constraint description and the value. + + Constraints that need to provide additional details, + such as where the error occured can override this. + + The MessageWriter on which to display the message + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Test whether the constraint is satisfied by an + ActualValueDelegate that returns the value to be tested. + The default implementation simply evaluates the delegate + but derived classes may override it to provide for delayed + processing. + + An + True for success, false for failure + + + + Test whether the constraint is satisfied by a given reference. + The default implementation simply dereferences the value but + derived classes may override it to provide for delayed processing. + + A reference to the value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Default override of ToString returns the constraint DisplayName + followed by any arguments within angle brackets. + + + + + + Returns the string representation of this constraint + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if the + argument constraint is not satisfied. + + + + + Returns a DelayedConstraint with the specified delay time. + + The delay in milliseconds. + + + + + Returns a DelayedConstraint with the specified delay time + and polling interval. + + The delay in milliseconds. + The interval at which to test the constraint. + + + + + The display name of this Constraint for use by ToString(). + The default value is the name of the constraint with + trailing "Constraint" removed. Derived classes may set + this to another name in their constructors. + + + + + Returns a ConstraintExpression by appending And + to the current constraint. + + + + + Returns a ConstraintExpression by appending And + to the current constraint. + + + + + Returns a ConstraintExpression by appending Or + to the current constraint. + + + + + Class used to detect any derived constraints + that fail to set the actual value in their + Matches override. + + + + + The base constraint + + + + + Construct given a base constraint + + + + + + Construct an AllItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + AndConstraint succeeds only if both members succeed. + + + + + BinaryConstraint is the abstract base of all constraints + that combine two other constraints in some fashion. + + + + + The first constraint being combined + + + + + The second constraint being combined + + + + + Construct a BinaryConstraint from two other constraints + + The first constraint + The second constraint + + + + Create an AndConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply both member constraints to an actual value, succeeding + succeeding only if both of them succeed. + + The actual value + True if the constraints both succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + AssignableFromConstraint is used to test that an object + can be assigned from a given Type. + + + + + TypeConstraint is the abstract base for constraints + that take a Type as their expected value. + + + + + The expected Type used by the constraint + + + + + Construct a TypeConstraint for a given Type + + + + + + Write the actual value for a failing constraint test to a + MessageWriter. TypeConstraints override this method to write + the name of the type. + + The writer on which the actual value is displayed + + + + Construct an AssignableFromConstraint for the type provided + + + + + + Test whether an object can be assigned from the specified type + + The object to be tested + True if the object can be assigned a value of the expected Type, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + AssignableToConstraint is used to test that an object + can be assigned to a given Type. + + + + + Construct an AssignableToConstraint for the type provided + + + + + + Test whether an object can be assigned to the specified type + + The object to be tested + True if the object can be assigned a value of the expected Type, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + AttributeConstraint tests that a specified attribute is present + on a Type or other provider and that the value of the attribute + satisfies some other constraint. + + + + + Constructs an AttributeConstraint for a specified attriute + Type and base constraint. + + + + + + + Determines whether the Type or other provider has the + expected attribute and if its value matches the + additional constraint specified. + + + + + Writes a description of the attribute to the specified writer. + + + + + Writes the actual value supplied to the specified writer. + + + + + Returns a string representation of the constraint. + + + + + AttributeExistsConstraint tests for the presence of a + specified attribute on a Type. + + + + + Constructs an AttributeExistsConstraint for a specific attribute Type + + + + + + Tests whether the object provides the expected attribute. + + A Type, MethodInfo, or other ICustomAttributeProvider + True if the expected attribute is present, otherwise false + + + + Writes the description of the constraint to the specified writer + + + + + BasicConstraint is the abstract base for constraints that + perform a simple comparison to a constant value. + + + + + Initializes a new instance of the class. + + The expected. + The description. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + BinarySerializableConstraint tests whether + an object is serializable in binary format. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation + + + + + CollectionConstraint is the abstract base class for + constraints that operate on collections. + + + + + Construct an empty CollectionConstraint + + + + + Construct a CollectionConstraint + + + + + + Determines whether the specified enumerable is empty. + + The enumerable. + + true if the specified enumerable is empty; otherwise, false. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Protected method to be implemented by derived classes + + + + + + + CollectionContainsConstraint is used to test whether a collection + contains an expected object as a member. + + + + + CollectionItemsEqualConstraint is the abstract base class for all + collection constraints that apply some notion of item equality + as a part of their operation. + + + + + Construct an empty CollectionConstraint + + + + + Construct a CollectionConstraint + + + + + + Flag the constraint to use the supplied EqualityAdapter. + NOTE: For internal use only. + + The EqualityAdapter to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Compares two collection members for equality + + + + + Return a new CollectionTally for use in making tests + + The collection to be included in the tally + + + + Flag the constraint to ignore case and return self. + + + + + Construct a CollectionContainsConstraint + + + + + + Test whether the expected item is contained in the collection + + + + + + + Write a descripton of the constraint to a MessageWriter + + + + + + CollectionEquivalentCOnstraint is used to determine whether two + collections are equivalent. + + + + + Construct a CollectionEquivalentConstraint + + + + + + Test whether two collections are equivalent + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionOrderedConstraint is used to test whether a collection is ordered. + + + + + Construct a CollectionOrderedConstraint + + + + + Modifies the constraint to use an IComparer and returns self. + + + + + Modifies the constraint to use an IComparer<T> and returns self. + + + + + Modifies the constraint to use a Comparison<T> and returns self. + + + + + Modifies the constraint to test ordering by the value of + a specified property and returns self. + + + + + Test whether the collection is ordered + + + + + + + Write a description of the constraint to a MessageWriter + + + + + + Returns the string representation of the constraint. + + + + + + If used performs a reverse comparison + + + + + CollectionSubsetConstraint is used to determine whether + one collection is a subset of another + + + + + Construct a CollectionSubsetConstraint + + The collection that the actual value is expected to be a subset of + + + + Test whether the actual collection is a subset of + the expected collection provided. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + CollectionTally counts (tallies) the number of + occurences of each object in one or more enumerations. + + + + + Construct a CollectionTally object from a comparer and a collection + + + + + Try to remove an object from the tally + + The object to remove + True if successful, false if the object was not found + + + + Try to remove a set of objects from the tally + + The objects to remove + True if successful, false if any object was not found + + + + The number of objects remaining in the tally + + + + + ComparisonAdapter class centralizes all comparisons of + values in NUnit, adapting to the use of any provided + IComparer, IComparer<T> or Comparison<T> + + + + + Returns a ComparisonAdapter that wraps an IComparer + + + + + Returns a ComparisonAdapter that wraps an IComparer<T> + + + + + Returns a ComparisonAdapter that wraps a Comparison<T> + + + + + Compares two objects + + + + + Gets the default ComparisonAdapter, which wraps an + NUnitComparer object. + + + + + Construct a ComparisonAdapter for an IComparer + + + + + Compares two objects + + + + + + + + Construct a default ComparisonAdapter + + + + + ComparisonAdapter<T> extends ComparisonAdapter and + allows use of an IComparer<T> or Comparison<T> + to actually perform the comparison. + + + + + Construct a ComparisonAdapter for an IComparer<T> + + + + + Compare a Type T to an object + + + + + Construct a ComparisonAdapter for a Comparison<T> + + + + + Compare a Type T to an object + + + + + Abstract base class for constraints that compare values to + determine if one is greater than, equal to or less than + the other. This class supplies the Using modifiers. + + + + + ComparisonAdapter to be used in making the comparison + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + + + Modifies the constraint to use an IComparer and returns self + + + + + Modifies the constraint to use an IComparer<T> and returns self + + + + + Modifies the constraint to use a Comparison<T> and returns self + + + + + Delegate used to delay evaluation of the actual value + to be used in evaluating a constraint + + + + + ConstraintBuilder maintains the stacks that are used in + processing a ConstraintExpression. An OperatorStack + is used to hold operators that are waiting for their + operands to be reognized. a ConstraintStack holds + input constraints as well as the results of each + operator applied. + + + + + Initializes a new instance of the class. + + + + + Appends the specified operator to the expression by first + reducing the operator stack and then pushing the new + operator on the stack. + + The operator to push. + + + + Appends the specified constraint to the expresson by pushing + it on the constraint stack. + + The constraint to push. + + + + Sets the top operator right context. + + The right context. + + + + Reduces the operator stack until the topmost item + precedence is greater than or equal to the target precedence. + + The target precedence. + + + + Resolves this instance, returning a Constraint. If the builder + is not currently in a resolvable state, an exception is thrown. + + The resolved constraint + + + + Gets a value indicating whether this instance is resolvable. + + + true if this instance is resolvable; otherwise, false. + + + + + OperatorStack is a type-safe stack for holding ConstraintOperators + + + + + Initializes a new instance of the class. + + The builder. + + + + Pushes the specified operator onto the stack. + + The op. + + + + Pops the topmost operator from the stack. + + + + + + Gets a value indicating whether this is empty. + + true if empty; otherwise, false. + + + + Gets the topmost operator without modifying the stack. + + The top. + + + + ConstraintStack is a type-safe stack for holding Constraints + + + + + Initializes a new instance of the class. + + The builder. + + + + Pushes the specified constraint. As a side effect, + the constraint's builder field is set to the + ConstraintBuilder owning this stack. + + The constraint. + + + + Pops this topmost constrait from the stack. + As a side effect, the constraint's builder + field is set to null. + + + + + + Gets a value indicating whether this is empty. + + true if empty; otherwise, false. + + + + Gets the topmost constraint without modifying the stack. + + The topmost constraint + + + + ConstraintExpression represents a compound constraint in the + process of being constructed from a series of syntactic elements. + + Individual elements are appended to the expression as they are + reognized. Once an actual Constraint is appended, the expression + returns a resolvable Constraint. + + + + + ConstraintExpressionBase is the abstract base class for the + ConstraintExpression class, which represents a + compound constraint in the process of being constructed + from a series of syntactic elements. + + NOTE: ConstraintExpressionBase is separate because the + ConstraintExpression class was generated in earlier + versions of NUnit. The two classes may be combined + in a future version. + + + + + The ConstraintBuilder holding the elements recognized so far + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the + class passing in a ConstraintBuilder, which may be pre-populated. + + The builder. + + + + Returns a string representation of the expression as it + currently stands. This should only be used for testing, + since it has the side-effect of resolving the expression. + + + + + + Appends an operator to the expression and returns the + resulting expression itself. + + + + + Appends a self-resolving operator to the expression and + returns a new ResolvableConstraintExpression. + + + + + Appends a constraint to the expression and returns that + constraint, which is associated with the current state + of the expression being built. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the + class passing in a ConstraintBuilder, which may be pre-populated. + + The builder. + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding only if a specified number of them succeed. + + + + + Returns a new PropertyConstraintExpression, which will either + test for the existence of the named property on the object + being tested or apply any following constraint to that property. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns a new AttributeConstraint checking for the + presence of a particular attribute on an object. + + + + + Returns the constraint provided as an argument - used to allow custom + custom constraints to easily participate in the syntax. + + + + + Returns the constraint provided as an argument - used to allow custom + custom constraints to easily participate in the syntax. + + + + + Returns a constraint that tests two items for equality + + + + + Returns a constraint that tests that two references are the same object + + + + + Returns a constraint that tests whether the + actual value is greater than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is greater than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the + actual value is less than or equal to the suppled argument + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual + value is of the exact type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is of the type supplied as an argument or a derived type. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is assignable from the type supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a collection containing the same elements as the + collection supplied as an argument. + + + + + Returns a constraint that tests whether the actual value + is a subset of the collection supplied as an argument. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new CollectionContainsConstraint checking for the + presence of a particular object in the collection. + + + + + Returns a new ContainsConstraint. This constraint + will, in turn, make use of the appropriate second-level + constraint, depending on the type of the actual argument. + This overload is only used if the item sought is a string, + since any other type implies that we are looking for a + collection member. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value contains the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value starts with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value ends with the substring supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that succeeds if the actual + value matches the regular expression supplied as an argument. + + + + + Returns a constraint that tests whether the path provided + is the same as an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the path provided + is the same path or under an expected path after canonicalization. + + + + + Returns a constraint that tests whether the actual value falls + within a specified range. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression that negates any + following constraint. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them succeed. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if at least one of them succeeds. + + + + + Returns a ConstraintExpression, which will apply + the following constraint to all members of a collection, + succeeding if all of them fail. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Length property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Count property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the Message property of the object being tested. + + + + + Returns a new ConstraintExpression, which will apply the following + constraint to the InnerException property of the object being tested. + + + + + With is currently a NOP - reserved for future use. + + + + + Returns a constraint that tests for null + + + + + Returns a constraint that tests for True + + + + + Returns a constraint that tests for False + + + + + Returns a constraint that tests for a positive value + + + + + Returns a constraint that tests for a negative value + + + + + Returns a constraint that tests for NaN + + + + + Returns a constraint that tests for empty + + + + + Returns a constraint that tests whether a collection + contains all unique items. + + + + + Returns a constraint that tests whether an object graph is serializable in binary format. + + + + + Returns a constraint that tests whether an object graph is serializable in xml format. + + + + + Returns a constraint that tests whether a collection is ordered + + + + + ContainsConstraint tests a whether a string contains a substring + or a collection contains an object. It postpones the decision of + which test to use until the type of the actual argument is known. + This allows testing whether a string is contained in a collection + or as a substring of another string using the same syntax. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to ignore case and return self. + + + + + Applies a delay to the match so that a match can be evaluated in the future. + + + + + Creates a new DelayedConstraint + + The inner constraint two decorate + The time interval after which the match is performed + If the value of is less than 0 + + + + Creates a new DelayedConstraint + + The inner constraint two decorate + The time interval after which the match is performed + The time interval used for polling + If the value of is less than 0 + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for if the base constraint fails, false if it succeeds + + + + Test whether the constraint is satisfied by a delegate + + The delegate whose value is to be tested + True for if the base constraint fails, false if it succeeds + + + + Test whether the constraint is satisfied by a given reference. + Overridden to wait for the specified delay period before + calling the base constraint with the dereferenced value. + + A reference to the value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a MessageWriter. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + EmptyCollectionConstraint tests whether a collection is empty. + + + + + Check that the collection is empty + + + + + + + Write the constraint description to a MessageWriter + + + + + + EmptyConstraint tests a whether a string or collection is empty, + postponing the decision about which test is applied until the + type of the actual argument is known. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EmptyDirectoryConstraint is used to test that a directory is empty + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + EmptyStringConstraint tests whether a string is empty. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EndsWithConstraint can test whether a string ends + with an expected substring. + + + + + StringConstraint is the abstract base for constraints + that operate on strings. It supports the IgnoreCase + modifier for string operations. + + + + + The expected value + + + + + Indicates whether tests should be case-insensitive + + + + + Constructs a StringConstraint given an expected value + + The expected value + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Test whether the constraint is satisfied by a given string + + The string to be tested + True for success, false for failure + + + + Modify the constraint to ignore case in matching. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + EqualConstraint is able to compare an actual value with the + expected value provided in its constructor. Two objects are + considered equal if both are null, or if both have the same + value. NUnit has special semantics for some object types. + + + + + If true, strings in error messages will be clipped + + + + + NUnitEqualityComparer used to test equality. + + + + + Initializes a new instance of the class. + + The expected value. + + + + Flag the constraint to use a tolerance when determining equality. + + Tolerance value to be used + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied Comparison object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Flag the constraint to use the supplied IEqualityComparer object. + + The IComparer object to use. + Self. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write a failure message. Overridden to provide custom + failure messages for EqualConstraint. + + The MessageWriter to write to + + + + Write description of this constraint + + The MessageWriter to write to + + + + Display the failure information for two collections that did not match. + + The MessageWriter on which to display + The expected collection. + The actual collection + The depth of this failure in a set of nested collections + + + + Displays a single line showing the types and sizes of the expected + and actual enumerations, collections or arrays. If both are identical, + the value is only shown once. + + The MessageWriter on which to display + The expected collection or array + The actual collection or array + The indentation level for the message line + + + + Displays a single line showing the point in the expected and actual + arrays at which the comparison failed. If the arrays have different + structures or dimensions, both values are shown. + + The MessageWriter on which to display + The expected array + The actual array + Index of the failure point in the underlying collections + The indentation level for the message line + + + + Display the failure information for two IEnumerables that did not match. + + The MessageWriter on which to display + The expected enumeration. + The actual enumeration + The depth of this failure in a set of nested collections + + + + Flag the constraint to ignore case and return self. + + + + + Flag the constraint to suppress string clipping + and return self. + + + + + Flag the constraint to compare arrays as collections + and return self. + + + + + Switches the .Within() modifier to interpret its tolerance as + a distance in representable values (see remarks). + + Self. + + Ulp stands for "unit in the last place" and describes the minimum + amount a given value can change. For any integers, an ulp is 1 whole + digit. For floating point values, the accuracy of which is better + for smaller numbers and worse for larger numbers, an ulp depends + on the size of the number. Using ulps for comparison of floating + point results instead of fixed tolerances is safer because it will + automatically compensate for the added inaccuracy of larger numbers. + + + + + Switches the .Within() modifier to interpret its tolerance as + a percentage that the actual values is allowed to deviate from + the expected value. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in days. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in hours. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in minutes. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in seconds. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in milliseconds. + + Self + + + + Causes the tolerance to be interpreted as a TimeSpan in clock ticks. + + Self + + + + EqualityAdapter class handles all equality comparisons + that use an IEqualityComparer, IEqualityComparer<T> + or a ComparisonAdapter. + + + + + Compares two objects, returning true if they are equal + + + + + Returns true if the two objects can be compared by this adapter. + The base adapter cannot handle IEnumerables except for strings. + + + + + Returns an EqualityAdapter that wraps an IComparer. + + + + + Returns an EqualityAdapter that wraps an IEqualityComparer. + + + + + Returns an EqualityAdapter that wraps an IEqualityComparer<T>. + + + + + Returns an EqualityAdapter that wraps an IComparer<T>. + + + + + Returns an EqualityAdapter that wraps a Comparison<T>. + + + + + EqualityAdapter that wraps an IComparer. + + + + + Returns true if the two objects can be compared by this adapter. + Generic adapter requires objects of the specified type. + + + + + EqualityAdapter that wraps an IComparer. + + + + + EqualityAdapterList represents a list of EqualityAdapters + in a common class across platforms. + + + + + ExactCountConstraint applies another constraint to each + item in a collection, succeeding only if a specified + number of items succeed. + + + + + Construct an ExactCountConstraint on top of an existing constraint + + + + + + + Apply the item constraint to each item in the collection, + succeeding only if the expected number of items pass. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + ExactTypeConstraint is used to test that an object + is of the exact type provided in the constructor + + + + + Construct an ExactTypeConstraint for a given Type + + The expected Type. + + + + Test that an object is of the exact type specified + + The actual value. + True if the tested object is of the exact type provided, otherwise false. + + + + Write the description of this constraint to a MessageWriter + + The MessageWriter to use + + + + ExceptionTypeConstraint is a special version of ExactTypeConstraint + used to provided detailed info about the exception thrown in + an error message. + + + + + Constructs an ExceptionTypeConstraint + + + + + Write the actual value for a failing constraint test to a + MessageWriter. Overriden to write additional information + in the case of an Exception. + + The MessageWriter to use + + + + FailurePoint class represents one point of failure + in an equality test. + + + + + The location of the failure + + + + + The expected value + + + + + The actual value + + + + + Indicates whether the expected value is valid + + + + + Indicates whether the actual value is valid + + + + + FailurePointList represents a set of FailurePoints + in a cross-platform way. + + + + + FalseConstraint tests that the actual value is false + + + + + Initializes a new instance of the class. + + + + Helper routines for working with floating point numbers + + + The floating point comparison code is based on this excellent article: + http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm + + + "ULP" means Unit in the Last Place and in the context of this library refers to + the distance between two adjacent floating point numbers. IEEE floating point + numbers can only represent a finite subset of natural numbers, with greater + accuracy for smaller numbers and lower accuracy for very large numbers. + + + If a comparison is allowed "2 ulps" of deviation, that means the values are + allowed to deviate by up to 2 adjacent floating point values, which might be + as low as 0.0000001 for small numbers or as high as 10.0 for large numbers. + + + + + Compares two floating point values for equality + First floating point value to be compared + Second floating point value t be compared + + Maximum number of representable floating point values that are allowed to + be between the left and the right floating point values + + True if both numbers are equal or close to being equal + + + Floating point values can only represent a finite subset of natural numbers. + For example, the values 2.00000000 and 2.00000024 can be stored in a float, + but nothing inbetween them. + + + This comparison will count how many possible floating point values are between + the left and the right number. If the number of possible values between both + numbers is less than or equal to maxUlps, then the numbers are considered as + being equal. + + + Implementation partially follows the code outlined here: + http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + + + + + Compares two double precision floating point values for equality + First double precision floating point value to be compared + Second double precision floating point value t be compared + + Maximum number of representable double precision floating point values that are + allowed to be between the left and the right double precision floating point values + + True if both numbers are equal or close to being equal + + + Double precision floating point values can only represent a limited series of + natural numbers. For example, the values 2.0000000000000000 and 2.0000000000000004 + can be stored in a double, but nothing inbetween them. + + + This comparison will count how many possible double precision floating point + values are between the left and the right number. If the number of possible + values between both numbers is less than or equal to maxUlps, then the numbers + are considered as being equal. + + + Implementation partially follows the code outlined here: + http://www.anttirt.net/2007/08/19/proper-floating-point-comparisons/ + + + + + + Reinterprets the memory contents of a floating point value as an integer value + + + Floating point value whose memory contents to reinterpret + + + The memory contents of the floating point value interpreted as an integer + + + + + Reinterprets the memory contents of a double precision floating point + value as an integer value + + + Double precision floating point value whose memory contents to reinterpret + + + The memory contents of the double precision floating point value + interpreted as an integer + + + + + Reinterprets the memory contents of an integer as a floating point value + + Integer value whose memory contents to reinterpret + + The memory contents of the integer value interpreted as a floating point value + + + + + Reinterprets the memory contents of an integer value as a double precision + floating point value + + Integer whose memory contents to reinterpret + + The memory contents of the integer interpreted as a double precision + floating point value + + + + Union of a floating point variable and an integer + + + The union's value as a floating point variable + + + The union's value as an integer + + + The union's value as an unsigned integer + + + Union of a double precision floating point variable and a long + + + The union's value as a double precision floating point variable + + + The union's value as a long + + + The union's value as an unsigned long + + + + Tests whether a value is greater than the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Tests whether a value is greater than or equal to the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + InstanceOfTypeConstraint is used to test that an object + is of the same type provided or derived from it. + + + + + Construct an InstanceOfTypeConstraint for the type provided + + The expected Type + + + + Test whether an object is of the specified type or a derived type + + The object to be tested + True if the object is of the provided type or derives from it, otherwise false. + + + + Write a description of this constraint to a MessageWriter + + The MessageWriter to use + + + + Tests whether a value is less than the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Tests whether a value is less than or equal to the value supplied to its constructor + + + + + The value against which a comparison is to be made + + + + + Initializes a new instance of the class. + + The expected value. + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Static methods used in creating messages + + + + + Static string used when strings are clipped + + + + + Returns the representation of a type as used in NUnitLite. + This is the same as Type.ToString() except for arrays, + which are displayed with their declared sizes. + + + + + + + Converts any control characters in a string + to their escaped representation. + + The string to be converted + The converted string + + + + Return the a string representation for a set of indices into an array + + Array of indices for which a string is needed + + + + Get an array of indices representing the point in a enumerable, + collection or array corresponding to a single int index into the + collection. + + The collection to which the indices apply + Index in the collection + Array of indices + + + + Clip a string to a given length, starting at a particular offset, returning the clipped + string with ellipses representing the removed parts + + The string to be clipped + The maximum permitted length of the result string + The point at which to start clipping + The clipped string + + + + Clip the expected and actual strings in a coordinated fashion, + so that they may be displayed together. + + + + + + + + + Shows the position two strings start to differ. Comparison + starts at the start index. + + The expected string + The actual string + The index in the strings at which comparison should start + Boolean indicating whether case should be ignored + -1 if no mismatch found, or the index where mismatch found + + + + NaNConstraint tests that the actual value is a double or float NaN + + + + + Test that the actual value is an NaN + + + + + + + Write the constraint description to a specified writer + + + + + + NoItemConstraint applies another constraint to each + item in a collection, failing if any of them succeeds. + + + + + Construct a NoItemConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + failing if any item fails. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + NotConstraint negates the effect of some other constraint + + + + + Initializes a new instance of the class. + + The base constraint to be negated. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for if the base constraint fails, false if it succeeds + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a MessageWriter. + + The writer on which the actual value is displayed + + + + NullConstraint tests that the actual value is null + + + + + Initializes a new instance of the class. + + + + + NullEmptyStringConstraint tests whether a string is either null or empty. + + + + + Constructs a new NullOrEmptyStringConstraint + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + The Numerics class contains common operations on numeric values. + + + + + Checks the type of the object, returning true if + the object is a numeric type. + + The object to check + true if the object is a numeric type + + + + Checks the type of the object, returning true if + the object is a floating point numeric type. + + The object to check + true if the object is a floating point numeric type + + + + Checks the type of the object, returning true if + the object is a fixed point numeric type. + + The object to check + true if the object is a fixed point numeric type + + + + Test two numeric values for equality, performing the usual numeric + conversions and using a provided or default tolerance. If the tolerance + provided is Empty, this method may set it to a default tolerance. + + The expected value + The actual value + A reference to the tolerance in effect + True if the values are equal + + + + Compare two numeric values, performing the usual numeric conversions. + + The expected value + The actual value + The relationship of the values to each other + + + + NUnitComparer encapsulates NUnit's default behavior + in comparing two objects. + + + + + Compares two objects + + + + + + + + Returns the default NUnitComparer. + + + + + Generic version of NUnitComparer + + + + + + Compare two objects of the same type + + + + + NUnitEqualityComparer encapsulates NUnit's handling of + equality tests between objects. + + + + + + + + + + Compares two objects for equality within a tolerance + + The first object to compare + The second object to compare + The tolerance to use in the comparison + + + + + If true, all string comparisons will ignore case + + + + + If true, arrays will be treated as collections, allowing + those of different dimensions to be compared + + + + + Comparison objects used in comparisons for some constraints. + + + + + List of points at which a failure occured. + + + + + RecursionDetector used to check for recursion when + evaluating self-referencing enumerables. + + + + + Compares two objects for equality within a tolerance, setting + the tolerance to the actual tolerance used if an empty + tolerance is supplied. + + + + + Helper method to compare two arrays + + + + + Method to compare two DirectoryInfo objects + + first directory to compare + second directory to compare + true if equivalent, false if not + + + + Returns the default NUnitEqualityComparer + + + + + Gets and sets a flag indicating whether case should + be ignored in determining equality. + + + + + Gets and sets a flag indicating that arrays should be + compared as collections, without regard to their shape. + + + + + Gets the list of external comparers to be used to + test for equality. They are applied to members of + collections, in place of NUnit's own logic. + + + + + Gets the list of failure points for the last Match performed. + The list consists of objects to be interpreted by the caller. + This generally means that the caller may only make use of + objects it has placed on the list at a particular depthy. + + + + + RecursionDetector detects when a comparison + between two enumerables has reached a point + where the same objects that were previously + compared are again being compared. This allows + the caller to stop the comparison if desired. + + + + + Check whether two objects have previously + been compared, returning true if they have. + The two objects are remembered, so that a + second call will always return true. + + + + + OrConstraint succeeds if either member succeeds + + + + + Create an OrConstraint from two other constraints + + The first constraint + The second constraint + + + + Apply the member constraints to an actual value, succeeding + succeeding as soon as one of them succeeds. + + The actual value + True if either constraint succeeded + + + + Write a description for this contraint to a MessageWriter + + The MessageWriter to receive the description + + + + PathConstraint serves as the abstract base of constraints + that operate on paths and provides several helper methods. + + + + + The expected path used in the constraint + + + + + Flag indicating whether a caseInsensitive comparison should be made + + + + + Construct a PathConstraint for a give expected path + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Returns true if the expected path and actual path match + + + + + Returns the string representation of this constraint + + + + + Transform the provided path to its canonical form so that it + may be more easily be compared with other paths. + + The original path + The path in canonical form + + + + Test whether one path in canonical form is under another. + + The first path - supposed to be the parent path + The second path - supposed to be the child path + Indicates whether case should be ignored + + + + + Modifies the current instance to be case-insensitve + and returns it. + + + + + Modifies the current instance to be case-sensitve + and returns it. + + + + + Predicate constraint wraps a Predicate in a constraint, + returning success if the predicate is true. + + + + + Construct a PredicateConstraint from a predicate + + + + + Determines whether the predicate succeeds when applied + to the actual value. + + + + + Writes the description to a MessageWriter + + + + + PropertyConstraint extracts a named property and uses + its value as the actual value for a chained constraint. + + + + + Initializes a new instance of the class. + + The name. + The constraint to apply to the property. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + + PropertyExistsConstraint tests that a named property + exists on the object provided through Match. + + Originally, PropertyConstraint provided this feature + in addition to making optional tests on the vaue + of the property. The two constraints are now separate. + + + + + Initializes a new instance of the class. + + The name of the property. + + + + Test whether the property exists for a given object + + The object to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. + + The writer on which the actual value is displayed + + + + Returns the string representation of the constraint. + + + + + + RangeConstraint tests whether two values are within a + specified range. + + + + + Initializes a new instance of the class. + + From. + To. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + RegexConstraint can test whether a string matches + the pattern provided. + + + + + Initializes a new instance of the class. + + The pattern. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + ResolvableConstraintExpression is used to represent a compound + constraint being constructed at a point where the last operator + may either terminate the expression or may have additional + qualifying constraints added to it. + + It is used, for example, for a Property element or for + an Exception element, either of which may be optionally + followed by constraints that apply to the property or + exception. + + + + + Create a new instance of ResolvableConstraintExpression + + + + + Create a new instance of ResolvableConstraintExpression, + passing in a pre-populated ConstraintBuilder. + + + + + Resolve the current expression to a Constraint + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied only if both + argument constraints are satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if either + of the argument constraints is satisfied. + + + + + This operator creates a constraint that is satisfied if the + argument constraint is not satisfied. + + + + + Appends an And Operator to the expression + + + + + Appends an Or operator to the expression. + + + + + ReusableConstraint wraps a constraint expression after + resolving it so that it can be reused consistently. + + + + + Construct a ReusableConstraint from a constraint expression + + The expression to be resolved and reused + + + + Converts a constraint to a ReusableConstraint + + The constraint to be converted + A ReusableConstraint + + + + Returns the string representation of the constraint. + + A string representing the constraint + + + + Resolves the ReusableConstraint by returning the constraint + that it originally wrapped. + + A resolved constraint + + + + SameAsConstraint tests whether an object is identical to + the object passed to its constructor + + + + + Initializes a new instance of the class. + + The expected object. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Summary description for SamePathConstraint. + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SamePathOrUnderConstraint tests that one path is under another + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SomeItemsConstraint applies another constraint to each + item in a collection, succeeding if any of them succeeds. + + + + + Construct a SomeItemsConstraint on top of an existing constraint + + + + + + Apply the item constraint to each item in the collection, + succeeding if any item succeeds. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + StartsWithConstraint can test whether a string starts + with an expected substring. + + + + + Initializes a new instance of the class. + + The expected string + + + + Test whether the constraint is matched by the actual value. + This is a template method, which calls the IsMatch method + of the derived class. + + + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SubPathConstraint tests that the actual path is under the expected path + + + + + Initializes a new instance of the class. + + The expected path + + + + Test whether the constraint is satisfied by a given value + + The expected path + The actual path + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + SubstringConstraint can test whether a string contains + the expected substring. + + + + + Initializes a new instance of the class. + + The expected. + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + ThrowsConstraint is used to test the exception thrown by + a delegate by applying a constraint to it. + + + + + Initializes a new instance of the class, + using a constraint to be applied to the exception. + + A constraint to apply to the caught exception. + + + + Executes the code of the delegate and captures any exception. + If a non-null base constraint was provided, it applies that + constraint to the exception. + + A delegate representing the code to be tested + True if an exception is thrown and the constraint succeeds, otherwise false + + + + Converts an ActualValueDelegate to a TestDelegate + before calling the primary overload. + + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of this constraint + + + + + Get the actual exception thrown - used by Assert.Throws. + + + + + ThrowsNothingConstraint tests that a delegate does not + throw an exception. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True if no exception is thrown, otherwise false + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. Overridden in ThrowsNothingConstraint to write + information about the exception that was actually caught. + + The writer on which the actual value is displayed + + + + The Tolerance class generalizes the notion of a tolerance + within which an equality test succeeds. Normally, it is + used with numeric types, but it can be used with any + type that supports taking a difference between two + objects and comparing that difference to a value. + + + + + Constructs a linear tolerance of a specdified amount + + + + + Constructs a tolerance given an amount and ToleranceMode + + + + + Tests that the current Tolerance is linear with a + numeric value, throwing an exception if it is not. + + + + + Returns an empty Tolerance object, equivalent to + specifying no tolerance. In most cases, it results + in an exact match but for floats and doubles a + default tolerance may be used. + + + + + Returns a zero Tolerance object, equivalent to + specifying an exact match. + + + + + Gets the ToleranceMode for the current Tolerance + + + + + Gets the value of the current Tolerance instance. + + + + + Returns a new tolerance, using the current amount as a percentage. + + + + + Returns a new tolerance, using the current amount in Ulps. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of days. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of hours. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of minutes. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of seconds. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of milliseconds. + + + + + Returns a new tolerance with a TimeSpan as the amount, using + the current amount as a number of clock ticks. + + + + + Returns true if the current tolerance is empty. + + + + + Modes in which the tolerance value for a comparison can be interpreted. + + + + + The tolerance was created with a value, without specifying + how the value would be used. This is used to prevent setting + the mode more than once and is generally changed to Linear + upon execution of the test. + + + + + The tolerance is used as a numeric range within which + two compared values are considered to be equal. + + + + + Interprets the tolerance as the percentage by which + the two compared values my deviate from each other. + + + + + Compares two values based in their distance in + representable numbers. + + + + + TrueConstraint tests that the actual value is true + + + + + Initializes a new instance of the class. + + + + + UniqueItemsConstraint tests whether all the items in a + collection are unique. + + + + + Check that all items are unique. + + + + + + + Write a description of this constraint to a MessageWriter + + + + + + XmlSerializableConstraint tests whether + an object is serializable in XML format. + + + + + Test whether the constraint is satisfied by a given value + + The value to be tested + True for success, false for failure + + + + Write the constraint description to a MessageWriter + + The writer on which the description is displayed + + + + Write the actual value for a failing constraint test to a + MessageWriter. The default implementation simply writes + the raw value of actual, leaving it to the writer to + perform any formatting. + + The writer on which the actual value is displayed + + + + Returns the string representation of this constraint + + + + + Represents a constraint that succeeds if all the + members of a collection match a base constraint. + + + + + Abstract base for operators that indicate how to + apply a constraint to items in a collection. + + + + + PrefixOperator takes a single constraint and modifies + it's action in some way. + + + + + The ConstraintOperator class is used internally by a + ConstraintBuilder to represent an operator that + modifies or combines constraints. + + Constraint operators use left and right precedence + values to determine whether the top operator on the + stack should be reduced before pushing a new operator. + + + + + The precedence value used when the operator + is about to be pushed to the stack. + + + + + The precedence value used when the operator + is on the top of the stack. + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + The syntax element preceding this operator + + + + + The syntax element folowing this operator + + + + + The precedence value used when the operator + is about to be pushed to the stack. + + + + + The precedence value used when the operator + is on the top of the stack. + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Returns the constraint created by applying this + prefix to another constraint. + + + + + + + Constructs a CollectionOperator + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + they all succeed. + + + + + Operator that requires both it's arguments to succeed + + + + + Abstract base class for all binary operators + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Abstract method that produces a constraint by applying + the operator to its left and right constraint arguments. + + + + + Gets the left precedence of the operator + + + + + Gets the right precedence of the operator + + + + + Construct an AndOperator + + + + + Apply the operator to produce an AndConstraint + + + + + Operator that tests for the presence of a particular attribute + on a type and optionally applies further tests to the attribute. + + + + + Abstract base class for operators that are able to reduce to a + constraint whether or not another syntactic element follows. + + + + + Construct an AttributeOperator for a particular Type + + The Type of attribute tested + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + Represents a constraint that succeeds if the specified + count of members of a collection match a base constraint. + + + + + Construct an ExactCountOperator for a specified count + + The expected count + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + none of them succeed. + + + + + Represents a constraint that succeeds if none of the + members of a collection match a base constraint. + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + none of them succeed. + + + + + Negates the test of the constraint it wraps. + + + + + Constructs a new NotOperator + + + + + Returns a NotConstraint applied to its argument. + + + + + Operator that requires at least one of it's arguments to succeed + + + + + Construct an OrOperator + + + + + Apply the operator to produce an OrConstraint + + + + + Operator used to test for the presence of a named Property + on an object and optionally apply further tests to the + value of that property. + + + + + Constructs a PropOperator for a particular named property + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + + Gets the name of the property to which the operator applies + + + + + Represents a constraint that succeeds if any of the + members of a collection match a base constraint. + + + + + Returns a constraint that will apply the argument + to the members of a collection, succeeding if + any of them succeed. + + + + + Operator that tests that an exception is thrown and + optionally applies further tests to the exception. + + + + + Construct a ThrowsOperator + + + + + Reduce produces a constraint from the operator and + any arguments. It takes the arguments from the constraint + stack and pushes the resulting constraint on it. + + + + + Represents a constraint that simply wraps the + constraint provided as an argument, without any + further functionality, but which modifes the + order of evaluation because of its precedence. + + + + + Constructor for the WithOperator + + + + + Returns a constraint that wraps its argument + + + + + Thrown when an assertion failed. + + + + The error message that explains + the reason for the exception + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when an assertion failed. + + + + + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when a test executes inconclusively. + + + + The error message that explains + the reason for the exception + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + Thrown when an assertion failed. + + + + + + + The error message that explains + the reason for the exception + The exception that caused the + current exception + + + + Serialization Constructor + + + + + + + + + + + Compares two objects of a given Type for equality within a tolerance + + The first object to compare + The second object to compare + The tolerance to use in the comparison + + + + diff --git a/samples/client/petstore/csharp/SwaggerClientTest/packages/NUnit.2.6.3/license.txt b/samples/client/petstore/csharp/SwaggerClientTest/packages/NUnit.2.6.3/license.txt new file mode 100644 index 00000000000..b12903afb5e --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientTest/packages/NUnit.2.6.3/license.txt @@ -0,0 +1,15 @@ +Copyright © 2002-2013 Charlie Poole +Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov +Copyright © 2000-2002 Philip A. Craig + +This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. + +Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: + +1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment (see the following) in the product documentation is required. + +Portions Copyright © 2002-2013 Charlie Poole or Copyright © 2002-2004 James W. Newkirk, Michael C. Two, Alexei A. Vorontsov or Copyright © 2000-2002 Philip A. Craig + +2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. + +3. This notice may not be removed or altered from any source distribution. diff --git a/samples/client/petstore/csharp/SwaggerClientTest/packages/repositories.config b/samples/client/petstore/csharp/SwaggerClientTest/packages/repositories.config new file mode 100644 index 00000000000..ba8d0d576a8 --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientTest/packages/repositories.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From acf09da5787728fdfc56defd29f0912f5bb5743c Mon Sep 17 00:00:00 2001 From: geekerzp Date: Mon, 22 Jun 2015 16:35:15 +0800 Subject: [PATCH 28/67] Fix typo in python codegen --- .../codegen/languages/PythonClientCodegen.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java index cdafa337c21..475a816aa5c 100755 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PythonClientCodegen.java @@ -81,17 +81,17 @@ public class PythonClientCodegen extends DefaultCodegen implements CodegenConfig additionalProperties.put("packageName", packageName); additionalProperties.put("packageVersion", packageVersion); - String swaggerFoler = packageName; + String swaggerFolder = packageName; - modelPackage = swaggerFoler + File.separatorChar + "models"; - apiPackage = swaggerFoler + File.separatorChar + "apis"; + modelPackage = swaggerFolder + File.separatorChar + "models"; + apiPackage = swaggerFolder + File.separatorChar + "apis"; supportingFiles.add(new SupportingFile("README.mustache", "", "README.md")); supportingFiles.add(new SupportingFile("setup.mustache", "", "setup.py")); - supportingFiles.add(new SupportingFile("api_client.mustache", swaggerFoler, "api_client.py")); - supportingFiles.add(new SupportingFile("rest.mustache", swaggerFoler, "rest.py")); - supportingFiles.add(new SupportingFile("configuration.mustache", swaggerFoler, "configuration.py")); - supportingFiles.add(new SupportingFile("__init__package.mustache", swaggerFoler, "__init__.py")); + supportingFiles.add(new SupportingFile("api_client.mustache", swaggerFolder, "api_client.py")); + supportingFiles.add(new SupportingFile("rest.mustache", swaggerFolder, "rest.py")); + supportingFiles.add(new SupportingFile("configuration.mustache", swaggerFolder, "configuration.py")); + supportingFiles.add(new SupportingFile("__init__package.mustache", swaggerFolder, "__init__.py")); supportingFiles.add(new SupportingFile("__init__model.mustache", modelPackage, "__init__.py")); supportingFiles.add(new SupportingFile("__init__api.mustache", apiPackage, "__init__.py")); } From b9ca19168a92d989bd91a2096bd16f7dceb8b540 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 08:28:22 -0700 Subject: [PATCH 29/67] remove static fields in Configuration and make variable case more consistent --- .../src/main/resources/php/ApiClient.mustache | 116 +++++++------ .../src/main/resources/php/api.mustache | 30 ++-- .../main/resources/php/configuration.mustache | 159 ++++++++++++++++-- .../src/main/resources/php/model.mustache | 2 +- 4 files changed, 221 insertions(+), 86 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index 4a3e50dd50b..8a030079fa0 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -29,40 +29,46 @@ class ApiClient { public static $PUT = "PUT"; public static $DELETE = "DELETE"; - private static $default_header = array(); + protected $defaultHeaders = array(); /* * @var string timeout (second) of the HTTP request, by default set to 0, no timeout */ - protected $curl_timeout = 0; + protected $curlTimeout = 0; /* * @var string user agent of the HTTP request, set to "PHP-Swagger" by default */ - protected $user_agent = "PHP-Swagger"; + protected $userAgent = "PHP-Swagger"; /** - * @param string $host Base url of the API server (optional) + * @var ApiConfiguration */ - function __construct($host = null) { - if ($host === null) { - $this->host = '{{basePath}}'; - } else { - $this->host = $host; + protected $config; + + /** + * @param ApiConfiguration $config config for this ApiClient + */ + function __construct(ApiConfiguration $config = null) { + if ($config == null) { + $config = ApiConfiguration::getDefaultConfiguration(); } + + $this->config = $config; } /** * add default header * - * @param string $header_name header name (e.g. Token) - * @param string $header_value header value (e.g. 1z8wp3) + * @param string $headerName header name (e.g. Token) + * @param string $headerValue header value (e.g. 1z8wp3) */ - public function addDefaultHeader($header_name, $header_value) { - if (!is_string($header_name)) + public function addDefaultHeader($headerName, $headerValue) { + if (!is_string($headerName)) { throw new \InvalidArgumentException('Header name must be a string.'); + } - self::$default_header[$header_name] = $header_value; + $this->defaultHeaders[$headerName] = $headerValue; } /** @@ -70,29 +76,29 @@ class ApiClient { * * @return array default header */ - public function getDefaultHeader() { - return self::$default_header; + public function getDefaultHeaders() { + return $this->defaultHeaders; } /** * delete the default header based on header name * - * @param string $header_name header name (e.g. Token) + * @param string $headerName header name (e.g. Token) */ - public function deleteDefaultHeader($header_name) { - unset(self::$default_header[$header_name]); + public function deleteDefaultHeader($headerName) { + unset($this->defaultHeaders[$headerName]); } /** * set the user agent of the api client * - * @param string $user_agent the user agent of the api client + * @param string $userAgent the user agent of the api client */ - public function setUserAgent($user_agent) { - if (!is_string($user_agent)) + public function setUserAgent($userAgent) { + if (!is_string($userAgent)) throw new \InvalidArgumentException('User-agent must be a string.'); - $this->user_agent= $user_agent; + $this->userAgent = $userAgent; } /** @@ -100,8 +106,8 @@ class ApiClient { * * @return string user agent */ - public function getUserAgent($user_agent) { - return $this->user_agent; + public function getUserAgent() { + return $this->userAgent; } /** @@ -113,7 +119,7 @@ class ApiClient { if (!is_numeric($seconds) || $seconds < 0) throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); - $this->curl_timeout = $seconds; + $this->curlTimeout = $seconds; } /** @@ -122,27 +128,34 @@ class ApiClient { * @return string HTTP timeout value */ public function getTimeout() { - return $this->curl_timeout; + return $this->curlTimeout; } /** * Get API key (with prefix if set) - * @param string key name + * @param string $apiKey name of apikey * @return string API key with the prefix */ public function getApiKeyWithPrefix($apiKey) { - if (isset(Configuration::$apiKeyPrefix[$apiKey])) { - return Configuration::$apiKeyPrefix[$apiKey]." ".Configuration::$apiKey[$apiKey]; - } else if (isset(Configuration::$apiKey[$apiKey])) { - return Configuration::$apiKey[$apiKey]; - } else { - return; + $prefix = $this->config->getApiKeyPrefix($apiKey); + $apiKey = $this->config->getApiKey($apiKey); + + if (!isset($apiKey)) { + return null; } + + if (isset($prefix)) { + $keyWithPrefix = $prefix." ".$apiKey; + } else { + $keyWithPrefix = $apiKey; + } + + return $keyWithPrefix; } /** - * update hearder and query param based on authentication setting + * update header and query param based on authentication setting * * @param array $headerParams header parameters (by ref) * @param array $queryParams query parameters (by ref) @@ -159,7 +172,7 @@ class ApiClient { switch($auth) { {{#authMethods}} case '{{name}}': - {{#isApiKey}}{{#isKeyInHeader}}$headerParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInHeader}}{{#isKeyInQuery}}$queryParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}$headerParams['Authorization'] = 'Basic '.base64_encode(Configuration::$username.":".Configuration::$password);{{/isBasic}} + {{#isApiKey}}{{#isKeyInHeader}}$headerParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInHeader}}{{#isKeyInQuery}}$queryParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}$headerParams['Authorization'] = 'Basic '.base64_encode($this->config->getUsername().":".$this->config->getPassword());{{/isBasic}} {{#isOAuth}}//TODO support oauth{{/isOAuth}} break; {{/authMethods}} @@ -175,6 +188,8 @@ class ApiClient { * @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 + * @param array $authSettings parameters for authentication + * @throws \{{invokerNamespace}}\ApiException on a non 2xx response * @return mixed */ public function callApi($resourcePath, $method, $queryParams, $postData, @@ -186,7 +201,7 @@ class ApiClient { $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); # construct the http header - $headerParams = array_merge((array)self::$default_header, (array)$headerParams); + $headerParams = array_merge((array)$this->defaultHeaders, (array)$headerParams); foreach ($headerParams as $key => $val) { $headers[] = "$key: $val"; @@ -200,12 +215,12 @@ class ApiClient { $postData = json_encode($this->sanitizeForSerialization($postData)); } - $url = $this->host . $resourcePath; + $url = $this->config->getHost() . $resourcePath; $curl = curl_init(); // set timeout, if needed - if ($this->curl_timeout != 0) { - curl_setopt($curl, CURLOPT_TIMEOUT, $this->curl_timeout); + if ($this->curlTimeout != 0) { + curl_setopt($curl, CURLOPT_TIMEOUT, $this->curlTimeout); } // return the result on success, rather than just TRUE curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); @@ -234,14 +249,14 @@ class ApiClient { curl_setopt($curl, CURLOPT_URL, $url); // Set user agent - curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent); + curl_setopt($curl, CURLOPT_USERAGENT, $this->userAgent); // debugging for curl - if (Configuration::$debug) { - error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, Configuration::$debug_file); + if ($this->config->getDebug()) { + error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, $this->config->getDebugFile()); curl_setopt($curl, CURLOPT_VERBOSE, 1); - curl_setopt($curl, CURLOPT_STDERR, fopen(Configuration::$debug_file, 'a')); + curl_setopt($curl, CURLOPT_STDERR, fopen($this->config->getDebugFile(), 'a')); } else { curl_setopt($curl, CURLOPT_VERBOSE, 0); } @@ -257,8 +272,8 @@ class ApiClient { $response_info = curl_getinfo($curl); // debug HTTP response body - if (Configuration::$debug) { - error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, Configuration::$debug_file); + if ($this->config->getDebug()) { + error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, $this->config->getDebugFile()); } // Handle the response @@ -278,9 +293,10 @@ class ApiClient { /** * Build a JSON POST object + * @param mixed $data the data to serialize + * @return string serialized form of $data */ - protected function sanitizeForSerialization($data) - { + protected function sanitizeForSerialization($data) { if (is_scalar($data) || null === $data) { $sanitized = $data; } else if ($data instanceof \DateTime) { @@ -372,7 +388,7 @@ class ApiClient { /** * Deserialize a JSON string into an object * - * @param object $object object or primitive to be deserialized + * @param object $data object or primitive to be deserialized * @param string $class class name is passed as a string * @return object an instance of $class */ @@ -419,7 +435,7 @@ class ApiClient { /* * return the header 'Accept' based on an array of Accept provided * - * @param array[string] $accept Array of header + * @param string[] $accept Array of header * @return string Accept (e.g. application/json) */ public static function selectHeaderAccept($accept) { diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 704f1c5ebab..2b4f1f27ab7 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -37,16 +37,11 @@ class {{classname}} { private $apiClient; function __construct($apiClient = null) { - if (null === $apiClient) { - if (Configuration::$apiClient === null) { - Configuration::$apiClient = new ApiClient(); // create a new API client if not present - $this->apiClient = Configuration::$apiClient; - } - else - $this->apiClient = Configuration::$apiClient; // use the default one - } else { - $this->apiClient = $apiClient; // use the one provided by the user + if ($apiClient == null) { + $apiClient = new ApiClient(); } + + $this->apiClient = $apiClient; } /** @@ -88,28 +83,29 @@ class {{classname}} { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array({{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}})); + $_header_accept = ApiClient::selectHeaderAccept(array({{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}})); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array({{#consumes}}'{{mediaType}}'{{#hasMore}},{{/hasMore}}{{/consumes}})); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array({{#consumes}}'{{mediaType}}'{{#hasMore}},{{/hasMore}}{{/consumes}})); {{#queryParams}}// query params if(${{paramName}} !== null) { - $queryParams['{{baseName}}'] = $this->apiClient->toQueryValue(${{paramName}}); + $queryParams['{{baseName}}'] = ApiClient::toQueryValue(${{paramName}}); }{{/queryParams}} {{#headerParams}}// header params if(${{paramName}} !== null) { - $headerParams['{{baseName}}'] = $this->apiClient->toHeaderValue(${{paramName}}); + $headerParams['{{baseName}}'] = ApiClient::toHeaderValue(${{paramName}}); }{{/headerParams}} {{#pathParams}}// path params if(${{paramName}} !== null) { $resourcePath = str_replace("{" . "{{baseName}}" . "}", - $this->apiClient->toPathValue(${{paramName}}), $resourcePath); + ApiClient::toPathValue(${{paramName}}), + $resourcePath); }{{/pathParams}} {{#formParams}}// form params if (${{paramName}} !== null) { - $formParams['{{baseName}}'] = {{#isFile}}'@' . {{/isFile}}$this->apiClient->toFormValue(${{paramName}}); + $formParams['{{baseName}}'] = {{#isFile}}'@' . {{/isFile}}ApiClient::toFormValue(${{paramName}}); }{{/formParams}} {{#bodyParams}}// body params $_tempBody = null; @@ -138,7 +134,7 @@ class {{classname}} { switch ($e->getCode()) { {{#responses}}{{#dataType}} case {{code}}: - $data = $this->apiClient->deserialize($e->getResponseBody(), '{{dataType}}'); + $data = ApiClient::deserialize($e->getResponseBody(), '{{dataType}}'); $throw = new ApiException("{{message}}", $e->getCode(), $e->getResponseHeaders(), $data); break;{{/dataType}}{{/responses}} } @@ -150,7 +146,7 @@ class {{classname}} { return null; } - $responseObject = $this->apiClient->deserialize($response,'{{returnType}}'); + $responseObject = ApiClient::deserialize($response,'{{returnType}}'); return $responseObject; {{/returnType}} } diff --git a/modules/swagger-codegen/src/main/resources/php/configuration.mustache b/modules/swagger-codegen/src/main/resources/php/configuration.mustache index b7a9107e77b..1f0ebb496ab 100644 --- a/modules/swagger-codegen/src/main/resources/php/configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/php/configuration.mustache @@ -17,50 +17,173 @@ namespace {{invokerNamespace}}; -class Configuration { +class ApiConfiguration { + + private static $defaultConfiguration = null; + + /** + * The host (from basePath) + */ + protected $host = '{{basePath}}'; /** * Associate array to store API key(s) */ - public static $apiKey = array(); + protected $apiKeys = array(); /** * Associate array to store API prefix (e.g. Bearer) */ - public static $apiKeyPrefix = array(); + protected $apiKeyPrefixes = array(); /** * Username for HTTP basic authentication */ - public static $username = ''; + protected $username = ''; /** * Password for HTTP basic authentication */ - public static $password = ''; - - /** - * The default instance of ApiClient - */ - public static $apiClient; + protected $password = ''; /** * Debug switch (default set to false) */ - public static $debug = false; + protected $debug = false; /** * Debug file location (log to STDOUT by default) */ - public static $debug_file = 'php://output'; + protected $debugFile = 'php://output'; - /* - * manually initalize ApiClient + /** + * @param string $host + * @return ApiConfiguration */ - public static function init() { - if (self::$apiClient === null) - self::$apiClient = new ApiClient(); + public function setHost($host) { + $this->host = $host; + return $this; } -} + /** + * @return string + */ + public function getHost() { + return $this->host; + } + /** + * @param string $key + * @param string $value + * @return ApiConfiguration + */ + public function setApiKey($key, $value) { + $this->apiKeys[$key] = $value; + return $this; + } + + /** + * @param $key + * @return string + */ + public function getApiKey($key) { + return isset($this->apiKeys[$key]) ? $this->apiKeys[$key] : null; + } + + /** + * @param string $key + * @param string $value + * @return ApiConfiguration + */ + public function setApiKeyPrefix($key, $value) { + $this->apiKeyPrefixes[$key] = $value; + return $this; + } + + /** + * @param $key + * @return string + */ + public function getApiKeyPrefix($key) { + return isset($this->apiKeyPrefixes[$key]) ? $this->apiKeyPrefixes[$key] : null; + } + + /** + * @param string $username + * @return ApiConfiguration + */ + public function setUsername($username) { + $this->username = $username; + return $this; + } + + /** + * @return string + */ + public function getUsername() { + return $this->username; + } + + /** + * @param string $password + * @return ApiConfiguration + */ + public function setPassword($password) { + $this->password = $password; + return $this; + } + + /** + * @return string + */ + public function getPassword() { + return $this->password; + } + + /** + * @param bool $debug + * @return ApiConfiguration + */ + public function setDebug($debug) { + $this->debug = $debug; + return $this; + } + + /** + * @return bool + */ + public function getDebug() { + return $this->debug; + } + + /** + * @param string $debugFile + * @return ApiConfiguration + */ + public function setDebugFile($debugFile) { + $this->debugFile = $debugFile; + return $this; + } + + /** + * @return string + */ + public function getDebugFile() { + return $this->debugFile; + } + + /** + * @return ApiConfiguration + */ + public static function getDefaultConfiguration() { + if (self::$defaultConfiguration == null) { + return new ApiConfiguration(); + } + + return self::$defaultConfiguration; + } + + public static function setDefaultConfiguration(ApiConfiguration $config) { + self::$defaultConfiguration = $config; + } +} diff --git a/modules/swagger-codegen/src/main/resources/php/model.mustache b/modules/swagger-codegen/src/main/resources/php/model.mustache index 86dafc99d99..fadf38f874b 100644 --- a/modules/swagger-codegen/src/main/resources/php/model.mustache +++ b/modules/swagger-codegen/src/main/resources/php/model.mustache @@ -44,7 +44,7 @@ class {{classname}} implements ArrayAccess { * {{{description}}}{{/description}} * @var {{{datatype}}} */ - public ${{name}}; + protected ${{name}}; {{/vars}} public function __construct(array $data = null) { if ($data != null) { From 99e963709b33f8075f5ce917de8e3eeb2f8bad99 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 08:30:08 -0700 Subject: [PATCH 30/67] renaming configuration --- .../java/io/swagger/codegen/languages/PhpClientCodegen.java | 2 +- .../php/{configuration.mustache => ApiConfiguration.mustache} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename modules/swagger-codegen/src/main/resources/php/{configuration.mustache => ApiConfiguration.mustache} (100%) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 7fb23157b36..18f8cb8917b 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -116,7 +116,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { setNamespacesFromPackages(); prefixPackages(); - supportingFiles.add(new SupportingFile("configuration.mustache", invokerPackage.replace('/', File.separatorChar), "Configuration.php")); + supportingFiles.add(new SupportingFile("ApiConfiguration.mustache", invokerPackage.replace('/', File.separatorChar), "ApiConfiguration.php")); supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerPackage.replace('/', File.separatorChar), "ApiClient.php")); supportingFiles.add(new SupportingFile("ApiException.mustache", invokerPackage.replace('/', File.separatorChar), "ApiException.php")); supportingFiles.add(new SupportingFile("composer.mustache", "", "composer.json")); diff --git a/modules/swagger-codegen/src/main/resources/php/configuration.mustache b/modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache similarity index 100% rename from modules/swagger-codegen/src/main/resources/php/configuration.mustache rename to modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache From 04be474f56fd019aa7c4022a8d81469f56acca11 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 08:36:49 -0700 Subject: [PATCH 31/67] moving $host back to ApiClient and making ApiClient setters fluent --- .../src/main/resources/php/ApiClient.mustache | 30 ++++++++++++++++++- .../resources/php/ApiConfiguration.mustache | 21 ------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index 8a030079fa0..e9e308cbf64 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -31,6 +31,11 @@ class ApiClient { protected $defaultHeaders = array(); + /** + * The host (from basePath) + */ + protected $host = '{{basePath}}'; + /* * @var string timeout (second) of the HTTP request, by default set to 0, no timeout */ @@ -49,7 +54,11 @@ class ApiClient { /** * @param ApiConfiguration $config config for this ApiClient */ - function __construct(ApiConfiguration $config = null) { + function __construct($host = null, ApiConfiguration $config = null) { + if ($host != null) { + $this->host = $host; + } + if ($config == null) { $config = ApiConfiguration::getDefaultConfiguration(); } @@ -69,6 +78,7 @@ class ApiClient { } $this->defaultHeaders[$headerName] = $headerValue; + return $this; } /** @@ -80,6 +90,22 @@ class ApiClient { return $this->defaultHeaders; } + /** + * @param string $host + * @return ApiConfiguration + */ + public function setHost($host) { + $this->host = $host; + return $this; + } + + /** + * @return string + */ + public function getHost() { + return $this->host; + } + /** * delete the default header based on header name * @@ -99,6 +125,7 @@ class ApiClient { throw new \InvalidArgumentException('User-agent must be a string.'); $this->userAgent = $userAgent; + return $this; } /** @@ -120,6 +147,7 @@ class ApiClient { throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); $this->curlTimeout = $seconds; + return $this; } /** diff --git a/modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache b/modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache index 1f0ebb496ab..764e0eafe89 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache @@ -21,11 +21,6 @@ class ApiConfiguration { private static $defaultConfiguration = null; - /** - * The host (from basePath) - */ - protected $host = '{{basePath}}'; - /** * Associate array to store API key(s) */ @@ -56,22 +51,6 @@ class ApiConfiguration { */ protected $debugFile = 'php://output'; - /** - * @param string $host - * @return ApiConfiguration - */ - public function setHost($host) { - $this->host = $host; - return $this; - } - - /** - * @return string - */ - public function getHost() { - return $this->host; - } - /** * @param string $key * @param string $value From b3a3bdd2e0c3a30809c7c132a03a668ca2e19465 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 09:18:41 -0700 Subject: [PATCH 32/67] add fully-qualified class names to deserialize params --- .../java/io/swagger/codegen/languages/PhpClientCodegen.java | 4 +++- .../src/main/resources/php/ApiClient.mustache | 6 +----- modules/swagger-codegen/src/main/resources/php/api.mustache | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 18f8cb8917b..7e9bac9c62f 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -8,6 +8,7 @@ import io.swagger.codegen.SupportingFile; import io.swagger.models.properties.ArrayProperty; import io.swagger.models.properties.MapProperty; import io.swagger.models.properties.Property; +import io.swagger.models.properties.RefProperty; import java.io.File; import java.util.ArrayList; @@ -157,6 +158,8 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { MapProperty mp = (MapProperty) p; Property inner = mp.getAdditionalProperties(); return getSwaggerType(p) + "[string," + getTypeDeclaration(inner) + "]"; + } else if (p instanceof RefProperty) { + return "\\\\" + modelNamespace.replace("\\", "\\\\") + "\\\\" + getSwaggerType(p); } return super.getTypeDeclaration(p); } @@ -256,7 +259,6 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public Map postProcessSupportingFileData(Map objs) { objs = addNamespaces(super.postProcessSupportingFileData(objs)); - objs = formatImports(objs, "models", "importPath"); return objs; } diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index e9e308cbf64..b91bbf29d37 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -17,10 +17,6 @@ namespace {{invokerNamespace}}; -{{#models}} -use {{importPath}}; -{{/models}} - class ApiClient { public static $PATCH = "PATCH"; @@ -416,7 +412,7 @@ class ApiClient { /** * Deserialize a JSON string into an object * - * @param object $data object or primitive to be deserialized + * @param mixed $data object or primitive to be deserialized * @param string $class class name is passed as a string * @return object an instance of $class */ diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 2b4f1f27ab7..76fe0afab5a 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -22,7 +22,7 @@ namespace {{apiNamespace}}; -use {{invokerNamespace}}\Configuration; +use {{invokerNamespace}}\ApiConfiguration; use {{invokerNamespace}}\ApiClient; use {{invokerNamespace}}\ApiException; From 1519912a1ab460ff0d2fae820b81f01b96a0e3b7 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 09:26:45 -0700 Subject: [PATCH 33/67] cleaning up some php doc --- .../swagger-codegen/src/main/resources/php/api.mustache | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 76fe0afab5a..06f6386b046 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -46,6 +46,7 @@ class {{classname}} { /** * get the API client + * @return ApiClient this API's client */ public function getApiClient() { return $this->apiClient; @@ -53,9 +54,12 @@ class {{classname}} { /** * set the API client + * @param ApiClient $apiClient + * @return {{classname}} */ - public function setApiClient($apiClient) { + public function setApiClient(ApiClient $apiClient) { $this->apiClient = $apiClient; + return $this; } {{#operation}} @@ -66,6 +70,7 @@ class {{classname}} { * {{#allParams}} * @param {{dataType}} ${{paramName}} {{description}} {{^optional}}(required){{/optional}}{{#optional}}(optional){{/optional}} {{/allParams}} * @return {{#returnType}}{{#isListContainer}}{{returnBaseType}}[]{{/isListContainer}}{{^isListContainer}}{{{returnType}}}{{/isListContainer}}{{/returnType}}{{^returnType}}void{{/returnType}} + * @throws \{{invokerNamespace}}\ApiException on non-2xx response */ public function {{nickname}}({{#allParams}}${{paramName}}{{#optional}}=null{{/optional}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { {{#allParams}}{{#required}} From 53bddae904cca40b53552b294e73803f9443e447 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 09:47:28 -0700 Subject: [PATCH 34/67] separate serialization responsibility to ObjectSerializer class --- .../codegen/languages/PhpClientCodegen.java | 1 + .../src/main/resources/php/ApiClient.mustache | 154 +----------------- .../resources/php/ObjectSerializer.mustache | 144 ++++++++++++++++ .../src/main/resources/php/api.mustache | 13 +- 4 files changed, 158 insertions(+), 154 deletions(-) create mode 100644 modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 7e9bac9c62f..201f7eb0539 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -120,6 +120,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { supportingFiles.add(new SupportingFile("ApiConfiguration.mustache", invokerPackage.replace('/', File.separatorChar), "ApiConfiguration.php")); supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerPackage.replace('/', File.separatorChar), "ApiClient.php")); supportingFiles.add(new SupportingFile("ApiException.mustache", invokerPackage.replace('/', File.separatorChar), "ApiException.php")); + supportingFiles.add(new SupportingFile("ObjectSerializer.mustache", invokerPackage.replace('/', File.separatorChar), "ObjectSerializer.php")); supportingFiles.add(new SupportingFile("composer.mustache", "", "composer.json")); supportingFiles.add(new SupportingFile("autoload.mustache", "", "autoload.php")); } diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index b91bbf29d37..e697b7305aa 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -50,11 +50,7 @@ class ApiClient { /** * @param ApiConfiguration $config config for this ApiClient */ - function __construct($host = null, ApiConfiguration $config = null) { - if ($host != null) { - $this->host = $host; - } - + function __construct(ApiConfiguration $config = null) { if ($config == null) { $config = ApiConfiguration::getDefaultConfiguration(); } @@ -67,6 +63,7 @@ class ApiClient { * * @param string $headerName header name (e.g. Token) * @param string $headerValue header value (e.g. 1z8wp3) + * @return ApiClient */ public function addDefaultHeader($headerName, $headerValue) { if (!is_string($headerName)) { @@ -115,6 +112,7 @@ class ApiClient { * set the user agent of the api client * * @param string $userAgent the user agent of the api client + * @return ApiClient */ public function setUserAgent($userAgent) { if (!is_string($userAgent)) @@ -137,6 +135,7 @@ class ApiClient { * set the HTTP timeout value * * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] + * @return ApiClient */ public function setTimeout($seconds) { if (!is_numeric($seconds) || $seconds < 0) @@ -236,10 +235,10 @@ class ApiClient { $postData = http_build_query($postData); } else if ((is_object($postData) or is_array($postData)) and !in_array('Content-Type: multipart/form-data', $headers)) { // json model - $postData = json_encode($this->sanitizeForSerialization($postData)); + $postData = json_encode(ObjectSerializer::sanitizeForSerialization($postData)); } - $url = $this->config->getHost() . $resourcePath; + $url = $this->getHost() . $resourcePath; $curl = curl_init(); // set timeout, if needed @@ -315,147 +314,6 @@ class ApiClient { return $data; } - /** - * Build a JSON POST object - * @param mixed $data the data to serialize - * @return string serialized form of $data - */ - 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) { - if ($data->$property !== null) { - $values[$data::$attributeMap[$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(self::toString($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 self::toString($object); - } - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the header. If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value a string which will be part of the header - * @return string the header string - */ - public static function toHeaderValue($value) { - return self::toString($value); - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the http body (form parameter). If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value the value of the form parameter - * @return string the form string - */ - public static function toFormValue($value) { - return self::toString($value); - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the parameter. If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value the value of the parameter - * @return string the header string - */ - public static function toString($value) { - if ($value instanceof \DateTime) { // datetime in ISO8601 format - return $value->format(\DateTime::ISO8601); - } - else { - return $value; - } - } - - /** - * Deserialize a JSON string into an object - * - * @param mixed $data 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; - } elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] - $inner = substr($class, 4, -1); - $deserialized = array(); - if(strrpos($inner, ",") !== false) { - $subClass_array = explode(',', $inner, 2); - $subClass = $subClass_array[1]; - foreach ($data as $key => $value) { - $deserialized[$key] = self::deserialize($value, $subClass); - } - } - } elseif (strcasecmp(substr($class, 0, 6),'array[') == 0) { - $subClass = substr($class, 6, -1); - $values = array(); - foreach ($data as $key => $value) { - $values[] = self::deserialize($value, $subClass); - } - $deserialized = $values; - } elseif ($class == 'DateTime') { - $deserialized = new \DateTime($data); - } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { - settype($data, $class); - $deserialized = $data; - } else { - $instance = new $class(); - foreach ($instance::$swaggerTypes as $property => $type) { - $original_property_name = $instance::$attributeMap[$property]; - if (isset($original_property_name) && isset($data->$original_property_name)) { - $instance->$property = self::deserialize($data->$original_property_name, $type); - } - } - $deserialized = $instance; - } - - return $deserialized; - } - /* * return the header 'Accept' based on an array of Accept provided * diff --git a/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache b/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache new file mode 100644 index 00000000000..3a7765a4a82 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache @@ -0,0 +1,144 @@ +format(\DateTime::ISO8601); + } else if (is_array($data)) { + foreach ($data as $property => $value) { + $data[$property] = self::sanitizeForSerialization($value); + } + $sanitized = $data; + } else if (is_object($data)) { + $values = array(); + foreach (array_keys($data::$swaggerTypes) as $property) { + if ($data->$property !== null) { + $values[$data::$attributeMap[$property]] = self::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(self::toString($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 self::toString($object); + } + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the header. If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value a string which will be part of the header + * @return string the header string + */ + public static function toHeaderValue($value) { + return self::toString($value); + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the http body (form parameter). If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value the value of the form parameter + * @return string the form string + */ + public static function toFormValue($value) { + return self::toString($value); + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the parameter. If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value the value of the parameter + * @return string the header string + */ + public static function toString($value) { + if ($value instanceof \DateTime) { // datetime in ISO8601 format + return $value->format(\DateTime::ISO8601); + } else { + return $value; + } + } + + /** + * Deserialize a JSON string into an object + * + * @param mixed $data 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; + } elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] + $inner = substr($class, 4, -1); + $deserialized = array(); + if(strrpos($inner, ",") !== false) { + $subClass_array = explode(',', $inner, 2); + $subClass = $subClass_array[1]; + foreach ($data as $key => $value) { + $deserialized[$key] = self::deserialize($value, $subClass); + } + } + } elseif (strcasecmp(substr($class, 0, 6),'array[') == 0) { + $subClass = substr($class, 6, -1); + $values = array(); + foreach ($data as $key => $value) { + $values[] = self::deserialize($value, $subClass); + } + $deserialized = $values; + } elseif ($class == 'DateTime') { + $deserialized = new \DateTime($data); + } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { + settype($data, $class); + $deserialized = $data; + } else { + $instance = new $class(); + foreach ($instance::$swaggerTypes as $property => $type) { + $original_property_name = $instance::$attributeMap[$property]; + if (isset($original_property_name) && isset($data->$original_property_name)) { + $instance->$property = self::deserialize($data->$original_property_name, $type); + } + } + $deserialized = $instance; + } + + return $deserialized; + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 06f6386b046..847527ee40c 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -25,6 +25,7 @@ namespace {{apiNamespace}}; use {{invokerNamespace}}\ApiConfiguration; use {{invokerNamespace}}\ApiClient; use {{invokerNamespace}}\ApiException; +use {{invokerNamespace}}\ObjectSerializer; {{#imports}} use {{{import}}}; @@ -96,21 +97,21 @@ class {{classname}} { {{#queryParams}}// query params if(${{paramName}} !== null) { - $queryParams['{{baseName}}'] = ApiClient::toQueryValue(${{paramName}}); + $queryParams['{{baseName}}'] = ObjectSerializer::toQueryValue(${{paramName}}); }{{/queryParams}} {{#headerParams}}// header params if(${{paramName}} !== null) { - $headerParams['{{baseName}}'] = ApiClient::toHeaderValue(${{paramName}}); + $headerParams['{{baseName}}'] = ObjectSerializer::toHeaderValue(${{paramName}}); }{{/headerParams}} {{#pathParams}}// path params if(${{paramName}} !== null) { $resourcePath = str_replace("{" . "{{baseName}}" . "}", - ApiClient::toPathValue(${{paramName}}), + ObjectSerializer::toPathValue(${{paramName}}), $resourcePath); }{{/pathParams}} {{#formParams}}// form params if (${{paramName}} !== null) { - $formParams['{{baseName}}'] = {{#isFile}}'@' . {{/isFile}}ApiClient::toFormValue(${{paramName}}); + $formParams['{{baseName}}'] = {{#isFile}}'@' . {{/isFile}}ObjectSerializer::toFormValue(${{paramName}}); }{{/formParams}} {{#bodyParams}}// body params $_tempBody = null; @@ -139,7 +140,7 @@ class {{classname}} { switch ($e->getCode()) { {{#responses}}{{#dataType}} case {{code}}: - $data = ApiClient::deserialize($e->getResponseBody(), '{{dataType}}'); + $data = ObjectSerializer::deserialize($e->getResponseBody(), '{{dataType}}'); $throw = new ApiException("{{message}}", $e->getCode(), $e->getResponseHeaders(), $data); break;{{/dataType}}{{/responses}} } @@ -151,7 +152,7 @@ class {{classname}} { return null; } - $responseObject = ApiClient::deserialize($response,'{{returnType}}'); + $responseObject = ObjectSerializer::deserialize($response,'{{returnType}}'); return $responseObject; {{/returnType}} } From e598384d97e5f3543679a3e7e6a38b2bf052a356 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 10:31:38 -0700 Subject: [PATCH 35/67] move authentication to the API level, so that supporting classes aren't api-specific --- .../src/main/resources/php/ApiClient.mustache | 43 ++++--------------- .../src/main/resources/php/api.mustache | 16 ++++--- 2 files changed, 19 insertions(+), 40 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index e697b7305aa..c2a6b369f3c 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -99,6 +99,14 @@ class ApiClient { return $this->host; } + /** + * get the config + * @return ApiConfiguration + */ + public function getConfig() { + return $this->config; + } + /** * delete the default header based on header name * @@ -176,34 +184,6 @@ class ApiClient { return $keyWithPrefix; } - - /** - * update header and query param based on authentication setting - * - * @param array $headerParams header parameters (by ref) - * @param array $queryParams query parameters (by ref) - * @param array $authSettings array of authentication scheme (e.g ['api_key']) - */ - public function updateParamsForAuth(&$headerParams, &$queryParams, $authSettings) - { - if (count($authSettings) == 0) - return; - - // one endpoint can have more than 1 auth settings - foreach($authSettings as $auth) { - // determine which one to use - switch($auth) { - {{#authMethods}} - case '{{name}}': - {{#isApiKey}}{{#isKeyInHeader}}$headerParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInHeader}}{{#isKeyInQuery}}$queryParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}$headerParams['Authorization'] = 'Basic '.base64_encode($this->config->getUsername().":".$this->config->getPassword());{{/isBasic}} - {{#isOAuth}}//TODO support oauth{{/isOAuth}} - break; - {{/authMethods}} - default: - //TODO show warning about security definition not found - } - } - } /** * @param string $resourcePath path to method endpoint @@ -211,18 +191,13 @@ class ApiClient { * @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 - * @param array $authSettings parameters for authentication * @throws \{{invokerNamespace}}\ApiException on a non 2xx response * @return mixed */ - public function callApi($resourcePath, $method, $queryParams, $postData, - $headerParams, $authSettings) { + public function callApi($resourcePath, $method, $queryParams, $postData, $headerParams) { $headers = array(); - # determine authentication setting - $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); - # construct the http header $headerParams = array_merge((array)$this->defaultHeaders, (array)$headerParams); diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 847527ee40c..a014ecbaccc 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -126,15 +126,19 @@ class {{classname}} { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array({{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}); - + {{#authMethods}}{{#isApiKey}} + $apiKey = $this->apiClient->getApiKeyWithPrefix('{{keyParamName}}'); + if (isset($apiKey)) { + {{#isKeyInHeader}}$headerParams['{{keyParamName}}'] = $apiKey;{{/isKeyInHeader}}{{#isKeyInQuery}}$queryParams['{{keyParamName}}'] = $apiKey;{{/isKeyInQuery}} + }{{/isApiKey}} + {{#isBasic}}$headerParams['Authorization'] = 'Basic '.base64_encode($this->apiClient->getConfig()->getUsername().":".$this->apiClient->getConfig()->getPassword());{{/isBasic}} + {{#isOAuth}}//TODO support oauth{{/isOAuth}} + {{/authMethods}} // make the API Call try { $response = $this->apiClient->callAPI($resourcePath, $method, $queryParams, $httpBody, - $headerParams, $authSettings); + $headerParams); } catch (ApiException $e) { $throw = $e; @@ -148,7 +152,7 @@ class {{classname}} { throw $throw; } {{#returnType}} - if(!$response) { + if (!$response) { return null; } From 6f11092a57442f5f2a73f155917ebfedcb8e9fd9 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 10:35:57 -0700 Subject: [PATCH 36/67] call setHost using API baspath when no apiclient is provided --- .../swagger-codegen/src/main/resources/php/ApiClient.mustache | 4 ++-- modules/swagger-codegen/src/main/resources/php/api.mustache | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index c2a6b369f3c..996ccbd16d9 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -28,9 +28,9 @@ class ApiClient { protected $defaultHeaders = array(); /** - * The host (from basePath) + * The host */ - protected $host = '{{basePath}}'; + protected $host = 'http://localhost'; /* * @var string timeout (second) of the HTTP request, by default set to 0, no timeout diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index a014ecbaccc..b6f17f528d5 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -39,7 +39,7 @@ class {{classname}} { function __construct($apiClient = null) { if ($apiClient == null) { - $apiClient = new ApiClient(); + $apiClient = (new ApiClient())->setHost('{{basePath}}'); } $this->apiClient = $apiClient; From 5de99bafa725b125dc5969d06d9fb93856ba2709 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 11:18:36 -0700 Subject: [PATCH 37/67] fixing package output --- .../java/io/swagger/codegen/languages/PhpClientCodegen.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 201f7eb0539..beddbeac729 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -126,7 +126,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { } protected String getSrcDir(String packageName) { - return rootNamespace + "/src/" + packageName; + return "src/" + packageName; } protected void prefixPackages() { From 109b7eeaec3c9ab0c70a1515cc8c58cd501da722 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 11:19:01 -0700 Subject: [PATCH 38/67] adding static setters/getters for models since members are no public --- .../resources/php/ObjectSerializer.mustache | 17 ++++++++++++----- .../src/main/resources/php/model.mustache | 18 ++++++++++++++---- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache b/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache index 3a7765a4a82..fe70c4db653 100644 --- a/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache @@ -21,8 +21,9 @@ class ObjectSerializer { } else if (is_object($data)) { $values = array(); foreach (array_keys($data::$swaggerTypes) as $property) { - if ($data->$property !== null) { - $values[$data::$attributeMap[$property]] = self::sanitizeForSerialization($data->$property); + $getter = $data::$getters[$property]; + if ($data->$getter() !== null) { + $values[$data::$attributeMap[$property]] = self::sanitizeForSerialization($data->$getter()); } } $sanitized = $values; @@ -131,9 +132,15 @@ class ObjectSerializer { } else { $instance = new $class(); foreach ($instance::$swaggerTypes as $property => $type) { - $original_property_name = $instance::$attributeMap[$property]; - if (isset($original_property_name) && isset($data->$original_property_name)) { - $instance->$property = self::deserialize($data->$original_property_name, $type); + $propertySetter = $instance::$setters[$property]; + + if (!isset($propertySetter) || !isset($data->{$instance::$attributeMap[$property]})) { + continue; + } + + $propertyValue = $data->{$instance::$attributeMap[$property]}; + if (isset($propertyValue)) { + $instance->$propertySetter(self::deserialize($propertyValue, $type)); } } $deserialized = $instance; diff --git a/modules/swagger-codegen/src/main/resources/php/model.mustache b/modules/swagger-codegen/src/main/resources/php/model.mustache index fadf38f874b..0e906b5885c 100644 --- a/modules/swagger-codegen/src/main/resources/php/model.mustache +++ b/modules/swagger-codegen/src/main/resources/php/model.mustache @@ -30,13 +30,23 @@ use \ArrayAccess; class {{classname}} implements ArrayAccess { static $swaggerTypes = array( - {{#vars}}'{{name}}' => '{{{datatype}}}'{{#hasMore}}, - {{/hasMore}}{{/vars}} + {{#vars}}'{{name}}' => '{{{datatype}}}'{{#hasMore}}, + {{/hasMore}}{{/vars}} ); static $attributeMap = array( - {{#vars}}'{{name}}' => '{{baseName}}'{{#hasMore}}, - {{/hasMore}}{{/vars}} + {{#vars}}'{{name}}' => '{{baseName}}'{{#hasMore}}, + {{/hasMore}}{{/vars}} + ); + + static $setters = array( + {{#vars}}'{{name}}' => '{{setter}}'{{#hasMore}}, + {{/hasMore}}{{/vars}} + ); + + static $getters = array( + {{#vars}}'{{name}}' => '{{getter}}'{{#hasMore}}, + {{/hasMore}}{{/vars}} ); {{#vars}} From 01d7776fc1a1469ea45bf4a1c2a81032cbf3bfe1 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 11:47:23 -0700 Subject: [PATCH 39/67] don't create a new response object, and keep the old string value in the exception and have the object as ApiException->responseObject --- .../main/resources/php/ApiException.mustache | 28 +++++++++++++++---- .../src/main/resources/php/api.mustache | 6 ++-- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/ApiException.mustache b/modules/swagger-codegen/src/main/resources/php/ApiException.mustache index 096979c11cb..4b8d205690c 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiException.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiException.mustache @@ -24,17 +24,22 @@ class ApiException extends Exception { /** * The HTTP body of the server response. */ - protected $response_body; + protected $responseBody; /** * The HTTP header of the server response. */ - protected $response_headers; + protected $responseHeaders; + + /** + * The deserialized response object + */ + protected $responseObject; public function __construct($message="", $code=0, $responseHeaders=null, $responseBody=null) { parent::__construct($message, $code); - $this->response_headers = $responseHeaders; - $this->response_body = $responseBody; + $this->responseHeaders = $responseHeaders; + $this->responseBody = $responseBody; } /** @@ -43,7 +48,7 @@ class ApiException extends Exception { * @return string HTTP response header */ public function getResponseHeaders() { - return $this->response_headers; + return $this->responseHeaders; } /** @@ -52,7 +57,18 @@ class ApiException extends Exception { * @return string HTTP response body */ public function getResponseBody() { - return $this->response_body; + return $this->responseBody; } + /** + * sets the deseralized response object (during deserialization) + * @param mixed $obj + */ + public function setResponseObject($obj) { + $this->responseObject = $obj; + } + + public function getResponseObject() { + return $this->responseObject; + } } diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index b6f17f528d5..3d9ead4bed1 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -140,16 +140,14 @@ class {{classname}} { $queryParams, $httpBody, $headerParams); } catch (ApiException $e) { - $throw = $e; - switch ($e->getCode()) { {{#responses}}{{#dataType}} case {{code}}: $data = ObjectSerializer::deserialize($e->getResponseBody(), '{{dataType}}'); - $throw = new ApiException("{{message}}", $e->getCode(), $e->getResponseHeaders(), $data); + $e->setResponseObject($data); break;{{/dataType}}{{/responses}} } - throw $throw; + throw $e; } {{#returnType}} if (!$response) { From a6331244e15fc09c34aaf16262d667ac9a137ccb Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 12:05:22 -0700 Subject: [PATCH 40/67] move all configuration to ApiConfiguration --- .../src/main/resources/php/ApiClient.mustache | 125 +----------------- .../resources/php/ApiConfiguration.mustache | 109 +++++++++++++++ 2 files changed, 114 insertions(+), 120 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index 996ccbd16d9..c29ca1f58e4 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -24,23 +24,6 @@ class ApiClient { public static $GET = "GET"; public static $PUT = "PUT"; public static $DELETE = "DELETE"; - - protected $defaultHeaders = array(); - - /** - * The host - */ - protected $host = 'http://localhost'; - - /* - * @var string timeout (second) of the HTTP request, by default set to 0, no timeout - */ - protected $curlTimeout = 0; - - /* - * @var string user agent of the HTTP request, set to "PHP-Swagger" by default - */ - protected $userAgent = "PHP-Swagger"; /** * @var ApiConfiguration @@ -58,47 +41,6 @@ class ApiClient { $this->config = $config; } - /** - * add default header - * - * @param string $headerName header name (e.g. Token) - * @param string $headerValue header value (e.g. 1z8wp3) - * @return ApiClient - */ - public function addDefaultHeader($headerName, $headerValue) { - if (!is_string($headerName)) { - throw new \InvalidArgumentException('Header name must be a string.'); - } - - $this->defaultHeaders[$headerName] = $headerValue; - return $this; - } - - /** - * get the default header - * - * @return array default header - */ - public function getDefaultHeaders() { - return $this->defaultHeaders; - } - - /** - * @param string $host - * @return ApiConfiguration - */ - public function setHost($host) { - $this->host = $host; - return $this; - } - - /** - * @return string - */ - public function getHost() { - return $this->host; - } - /** * get the config * @return ApiConfiguration @@ -107,62 +49,6 @@ class ApiClient { return $this->config; } - /** - * delete the default header based on header name - * - * @param string $headerName header name (e.g. Token) - */ - public function deleteDefaultHeader($headerName) { - unset($this->defaultHeaders[$headerName]); - } - - /** - * set the user agent of the api client - * - * @param string $userAgent the user agent of the api client - * @return ApiClient - */ - public function setUserAgent($userAgent) { - if (!is_string($userAgent)) - throw new \InvalidArgumentException('User-agent must be a string.'); - - $this->userAgent = $userAgent; - return $this; - } - - /** - * get the user agent of the api client - * - * @return string user agent - */ - public function getUserAgent() { - return $this->userAgent; - } - - /** - * set the HTTP timeout value - * - * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] - * @return ApiClient - */ - public function setTimeout($seconds) { - if (!is_numeric($seconds) || $seconds < 0) - throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); - - $this->curlTimeout = $seconds; - return $this; - } - - /** - * get the HTTP timeout value - * - * @return string HTTP timeout value - */ - public function getTimeout() { - return $this->curlTimeout; - } - - /** * Get API key (with prefix if set) * @param string $apiKey name of apikey @@ -199,7 +85,7 @@ class ApiClient { $headers = array(); # construct the http header - $headerParams = array_merge((array)$this->defaultHeaders, (array)$headerParams); + $headerParams = array_merge((array)$this->config->getDefaultHeaders(), (array)$headerParams); foreach ($headerParams as $key => $val) { $headers[] = "$key: $val"; @@ -213,12 +99,12 @@ class ApiClient { $postData = json_encode(ObjectSerializer::sanitizeForSerialization($postData)); } - $url = $this->getHost() . $resourcePath; + $url = $this->config->getHost() . $resourcePath; $curl = curl_init(); // set timeout, if needed - if ($this->curlTimeout != 0) { - curl_setopt($curl, CURLOPT_TIMEOUT, $this->curlTimeout); + if ($this->config->getCurlTimeout() != 0) { + curl_setopt($curl, CURLOPT_TIMEOUT, $this->config->getCurlTimeout()); } // return the result on success, rather than just TRUE curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); @@ -247,7 +133,7 @@ class ApiClient { curl_setopt($curl, CURLOPT_URL, $url); // Set user agent - curl_setopt($curl, CURLOPT_USERAGENT, $this->userAgent); + curl_setopt($curl, CURLOPT_USERAGENT, $this->config->getUserAgent()); // debugging for curl if ($this->config->getDebug()) { @@ -320,6 +206,5 @@ class ApiClient { return implode(',', $content_type); } } - } diff --git a/modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache b/modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache index 764e0eafe89..4834294901d 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache @@ -41,6 +41,26 @@ class ApiConfiguration { */ protected $password = ''; + /** + * default headers for requests this conf + */ + protected $defaultHeaders = array(); + + /** + * The host + */ + protected $host = 'http://localhost'; + + /* + * @var string timeout (second) of the HTTP request, by default set to 0, no timeout + */ + protected $curlTimeout = 0; + + /* + * @var string user agent of the HTTP request, set to "PHP-Swagger" by default + */ + protected $userAgent = "PHP-Swagger"; + /** * Debug switch (default set to false) */ @@ -119,6 +139,95 @@ class ApiConfiguration { return $this->password; } + /** + * add default header + * + * @param string $headerName header name (e.g. Token) + * @param string $headerValue header value (e.g. 1z8wp3) + * @return ApiClient + */ + public function addDefaultHeader($headerName, $headerValue) { + if (!is_string($headerName)) { + throw new \InvalidArgumentException('Header name must be a string.'); + } + + $this->defaultHeaders[$headerName] = $headerValue; + return $this; + } + + /** + * get the default header + * + * @return array default header + */ + public function getDefaultHeaders() { + return $this->defaultHeaders; + } + + /** + * @param string $host + * @return ApiConfiguration + */ + public function setHost($host) { + $this->host = $host; + return $this; + } + + /** + * @return string + */ + public function getHost() { + return $this->host; + } + + /** + * set the user agent of the api client + * + * @param string $userAgent the user agent of the api client + * @return ApiClient + */ + public function setUserAgent($userAgent) { + if (!is_string($userAgent)) { + throw new \InvalidArgumentException('User-agent must be a string.'); + } + + $this->userAgent = $userAgent; + return $this; + } + + /** + * get the user agent of the api client + * + * @return string user agent + */ + public function getUserAgent() { + return $this->userAgent; + } + + /** + * set the HTTP timeout value + * + * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] + * @return ApiClient + */ + public function setCurlTimeout($seconds) { + if (!is_numeric($seconds) || $seconds < 0) { + throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); + } + + $this->curlTimeout = $seconds; + return $this; + } + + /** + * get the HTTP timeout value + * + * @return string HTTP timeout value + */ + public function getCurlTimeout() { + return $this->curlTimeout; + } + /** * @param bool $debug * @return ApiConfiguration From 5ef50f9f4b27f943e841d04d6958926d9c2e8f48 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 12:07:48 -0700 Subject: [PATCH 41/67] rename ApiConfiguration to ApiClientConfiguration --- .../codegen/languages/PhpClientCodegen.java | 2 +- .../src/main/resources/php/ApiClient.mustache | 10 ++++----- ...stache => ApiClientConfiguration.mustache} | 22 +++++++++---------- .../src/main/resources/php/api.mustache | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) rename modules/swagger-codegen/src/main/resources/php/{ApiConfiguration.mustache => ApiClientConfiguration.mustache} (92%) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index beddbeac729..a9909427a0d 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -117,7 +117,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { setNamespacesFromPackages(); prefixPackages(); - supportingFiles.add(new SupportingFile("ApiConfiguration.mustache", invokerPackage.replace('/', File.separatorChar), "ApiConfiguration.php")); + supportingFiles.add(new SupportingFile("ApiClientConfiguration.mustache", invokerPackage.replace('/', File.separatorChar), "ApiClientConfiguration.php")); supportingFiles.add(new SupportingFile("ApiClient.mustache", invokerPackage.replace('/', File.separatorChar), "ApiClient.php")); supportingFiles.add(new SupportingFile("ApiException.mustache", invokerPackage.replace('/', File.separatorChar), "ApiException.php")); supportingFiles.add(new SupportingFile("ObjectSerializer.mustache", invokerPackage.replace('/', File.separatorChar), "ObjectSerializer.php")); diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index c29ca1f58e4..d6133b08584 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -26,16 +26,16 @@ class ApiClient { public static $DELETE = "DELETE"; /** - * @var ApiConfiguration + * @var ApiClientConfiguration */ protected $config; /** - * @param ApiConfiguration $config config for this ApiClient + * @param ApiClientConfiguration $config config for this ApiClient */ - function __construct(ApiConfiguration $config = null) { + function __construct(ApiClientConfiguration $config = null) { if ($config == null) { - $config = ApiConfiguration::getDefaultConfiguration(); + $config = ApiClientConfiguration::getDefaultConfiguration(); } $this->config = $config; @@ -43,7 +43,7 @@ class ApiClient { /** * get the config - * @return ApiConfiguration + * @return ApiClientConfiguration */ public function getConfig() { return $this->config; diff --git a/modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClientConfiguration.mustache similarity index 92% rename from modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache rename to modules/swagger-codegen/src/main/resources/php/ApiClientConfiguration.mustache index 4834294901d..6a674ccfd3f 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiConfiguration.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClientConfiguration.mustache @@ -17,7 +17,7 @@ namespace {{invokerNamespace}}; -class ApiConfiguration { +class ApiClientConfiguration { private static $defaultConfiguration = null; @@ -74,7 +74,7 @@ class ApiConfiguration { /** * @param string $key * @param string $value - * @return ApiConfiguration + * @return ApiClientConfiguration */ public function setApiKey($key, $value) { $this->apiKeys[$key] = $value; @@ -92,7 +92,7 @@ class ApiConfiguration { /** * @param string $key * @param string $value - * @return ApiConfiguration + * @return ApiClientConfiguration */ public function setApiKeyPrefix($key, $value) { $this->apiKeyPrefixes[$key] = $value; @@ -109,7 +109,7 @@ class ApiConfiguration { /** * @param string $username - * @return ApiConfiguration + * @return ApiClientConfiguration */ public function setUsername($username) { $this->username = $username; @@ -125,7 +125,7 @@ class ApiConfiguration { /** * @param string $password - * @return ApiConfiguration + * @return ApiClientConfiguration */ public function setPassword($password) { $this->password = $password; @@ -166,7 +166,7 @@ class ApiConfiguration { /** * @param string $host - * @return ApiConfiguration + * @return ApiClientConfiguration */ public function setHost($host) { $this->host = $host; @@ -230,7 +230,7 @@ class ApiConfiguration { /** * @param bool $debug - * @return ApiConfiguration + * @return ApiClientConfiguration */ public function setDebug($debug) { $this->debug = $debug; @@ -246,7 +246,7 @@ class ApiConfiguration { /** * @param string $debugFile - * @return ApiConfiguration + * @return ApiClientConfiguration */ public function setDebugFile($debugFile) { $this->debugFile = $debugFile; @@ -261,17 +261,17 @@ class ApiConfiguration { } /** - * @return ApiConfiguration + * @return ApiClientConfiguration */ public static function getDefaultConfiguration() { if (self::$defaultConfiguration == null) { - return new ApiConfiguration(); + return new ApiClientConfiguration(); } return self::$defaultConfiguration; } - public static function setDefaultConfiguration(ApiConfiguration $config) { + public static function setDefaultConfiguration(ApiClientConfiguration $config) { self::$defaultConfiguration = $config; } } diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 3d9ead4bed1..d276d1c652c 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -22,7 +22,7 @@ namespace {{apiNamespace}}; -use {{invokerNamespace}}\ApiConfiguration; +use {{invokerNamespace}}\ApiClientConfiguration; use {{invokerNamespace}}\ApiClient; use {{invokerNamespace}}\ApiException; use {{invokerNamespace}}\ObjectSerializer; From 8e15bd6a85e2a1cc5d04b8ac067d2daa33fbf146 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 12:13:39 -0700 Subject: [PATCH 42/67] call setHost on config --- modules/swagger-codegen/src/main/resources/php/api.mustache | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index d276d1c652c..6fb9fb5dd06 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -39,7 +39,8 @@ class {{classname}} { function __construct($apiClient = null) { if ($apiClient == null) { - $apiClient = (new ApiClient())->setHost('{{basePath}}'); + $apiClient = new ApiClient(); + $apiClient->getConfig()->setHost('{{basePath}}'); } $this->apiClient = $apiClient; From bd5eb7ace39123389184a103cb404ace51cc5d79 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 12:30:52 -0700 Subject: [PATCH 43/67] update tests --- .../java/io/swagger/codegen/languages/PhpClientCodegen.java | 2 ++ .../swagger-codegen/src/test/scala/php/PhpModelTest.scala | 6 +++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index a9909427a0d..5317530a9eb 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -41,6 +41,8 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { apiTemplateFiles.put("api.mustache", ".php"); templateDir = "php"; + setNamespacesFromPackages(); + reservedWords = new HashSet( Arrays.asList( "__halt_compiler", "abstract", "and", "array", "as", "break", "callable", "case", "catch", "class", "clone", "const", "continue", "declare", "default", "die", "do", "echo", "else", "elseif", "empty", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "eval", "exit", "extends", "final", "for", "foreach", "function", "global", "goto", "if", "implements", "include", "include_once", "instanceof", "insteadof", "interface", "isset", "list", "namespace", "new", "or", "print", "private", "protected", "public", "require", "require_once", "return", "static", "switch", "throw", "trait", "try", "unset", "use", "var", "while", "xor") diff --git a/modules/swagger-codegen/src/test/scala/php/PhpModelTest.scala b/modules/swagger-codegen/src/test/scala/php/PhpModelTest.scala index ade8a09e80d..fae3999bbbd 100644 --- a/modules/swagger-codegen/src/test/scala/php/PhpModelTest.scala +++ b/modules/swagger-codegen/src/test/scala/php/PhpModelTest.scala @@ -142,7 +142,7 @@ class PhpModelTest extends FlatSpec with Matchers { val vars = cm.vars vars.get(0).baseName should be("children") - vars.get(0).datatype should be("Children") + vars.get(0).datatype should be("\\\\Swagger\\\\Models\\\\Children") vars.get(0).name should be("children") vars.get(0).baseType should be("Children") vars.get(0).required should equal(null) @@ -166,7 +166,7 @@ class PhpModelTest extends FlatSpec with Matchers { val vars = cm.vars vars.get(0).baseName should be("children") vars.get(0).complexType should be("Children") - vars.get(0).datatype should be("array[Children]") + vars.get(0).datatype should be("array[\\\\Swagger\\\\Models\\\\Children]") vars.get(0).name should be("children") vars.get(0).baseType should be("array") vars.get(0).containerType should be("array") @@ -192,7 +192,7 @@ class PhpModelTest extends FlatSpec with Matchers { val vars = cm.vars vars.get(0).baseName should be("children") vars.get(0).complexType should be("Children") - vars.get(0).datatype should be("map[string,Children]") + vars.get(0).datatype should be("map[string,\\\\Swagger\\\\Models\\\\Children]") vars.get(0).name should be("children") vars.get(0).baseType should be("map") vars.get(0).containerType should be("map") From da14c9e6927ec78006e5c40c161f88a9706816f3 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 19:09:32 -0700 Subject: [PATCH 44/67] changing to invokerPackage --- .../src/main/resources/php/ApiClientConfiguration.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClientConfiguration.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClientConfiguration.mustache index 84b901f84e9..491f5a45dd8 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClientConfiguration.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClientConfiguration.mustache @@ -15,7 +15,7 @@ * limitations under the License. */ -namespace {{invokerNamespace}}; +namespace {{invokerPackage}}; class ApiClientConfiguration { From 4fe979a8c0e564cd8eebb123612488562fe29e2f Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 19:26:26 -0700 Subject: [PATCH 45/67] code compiles and *should* work, but need to re-organize for separate client/api-specific class namespaces --- .../codegen/languages/PhpClientCodegen.java | 155 +++++++----------- .../src/main/resources/php/ApiClient.mustache | 4 +- .../resources/php/ObjectSerializer.mustache | 2 +- .../src/main/resources/php/api.mustache | 6 +- 4 files changed, 63 insertions(+), 104 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index c362ce8da3b..88e7725578c 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -24,18 +24,10 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { protected String groupId = "swagger"; protected String artifactId = "swagger-client"; protected String artifactVersion = null; - protected String rootNamespace; - protected String invokerNamespace; - protected String modelNamespace; - protected String apiNamespace; public PhpClientCodegen() { super(); - rootNamespace = "Swagger"; - invokerPackage = "Client"; - modelPackage = "Models"; - apiPackage = "Api"; outputFolder = "generated-code/php"; modelTemplateFiles.put("model.mustache", ".php"); apiTemplateFiles.put("api.mustache", ".php"); @@ -95,7 +87,6 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("object", "object"); typeMapping.put("DateTime", "\\DateTime"); - cliOptions.add(new CliOption("rootNamespace", "root namespace from which other namespaces derive")); cliOptions.add(new CliOption("invokerPackage", "namespace for core, non-api-specific classes")); } @@ -138,20 +129,6 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { this.setInvokerPackage((String) additionalProperties.get("invokerPackage")); } - if (additionalProperties.containsKey("rootNamespace")) { - this.setRootNamespace((String) additionalProperties.get("rootNamespace")); - } - - prefixPackages(); - - // theirs - supportingFiles.add(new SupportingFile("composer.mustache", getPackagePath(), "composer.json")); - supportingFiles.add(new SupportingFile("configuration.mustache", toPackagePath(invokerPackage, "lib"), "Configuration.php")); - supportingFiles.add(new SupportingFile("ApiClient.mustache", toPackagePath(invokerPackage, "lib"), "ApiClient.php")); - supportingFiles.add(new SupportingFile("ApiException.mustache", toPackagePath(invokerPackage, "lib"), "ApiException.php")); - supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php")); - - // mine supportingFiles.add(new SupportingFile("ApiClientConfiguration.mustache", toPackagePath(invokerPackage, "lib"), "ApiClientConfiguration.php")); supportingFiles.add(new SupportingFile("ApiClient.mustache", toPackagePath(invokerPackage, "lib"), "ApiClient.php")); supportingFiles.add(new SupportingFile("ApiException.mustache", toPackagePath(invokerPackage, "lib"), "ApiException.php")); @@ -160,15 +137,15 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php")); } - protected String getSrcDir(String packageName) { - return "src/" + packageName; - } - - protected void prefixPackages() { - setApiPackage(getSrcDir(apiPackage)); - setInvokerPackage(getSrcDir(invokerPackage)); - setModelPackage(getSrcDir(modelPackage)); - } +// protected String getSrcDir(String packageName) { +// return "src/" + packageName; +// } +// +// protected void prefixPackages() { +// setApiPackage(getSrcDir(apiPackage)); +// setInvokerPackage(getSrcDir(invokerPackage)); +// setModelPackage(getSrcDir(modelPackage)); +// } @Override public String escapeReservedWord(String name) { @@ -238,10 +215,6 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { this.invokerPackage = invokerPackage; } - public void setRootNamespace(String rootNamespace) { - this.rootNamespace = rootNamespace; - } - @Override public String toVarName(String name) { // parameter name starting with number won't compile @@ -279,64 +252,54 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { return toModelName(name); } - public String toNamespace(String packageName) { - return rootNamespace + "\\" + packageName.replace('/', '\\').replace('.', '\\'); - } - - protected void setNamespacesFromPackages() { - invokerNamespace = toNamespace(invokerPackage); - apiNamespace = toNamespace(apiPackage); - modelNamespace = toNamespace(modelPackage); - } - - @Override - public Map postProcessModels(Map objs) { - return addNamespaces(super.postProcessModels(objs)); - } - - @Override - public Map postProcessOperations(Map objs) { - objs = addNamespaces(super.postProcessOperations(objs)); - objs = formatImports(objs, "imports", "import"); - - return objs; - } - - @Override - public Map postProcessSupportingFileData(Map objs) { - objs = addNamespaces(super.postProcessSupportingFileData(objs)); - - return objs; - } - - protected Map addNamespaces(Map objs) { - objs.put("rootNamespace", rootNamespace); - objs.put("invokerNamespace", invokerNamespace); - objs.put("apiNamespace", apiNamespace); - objs.put("modelNamespace", modelNamespace); - - return objs; - } - - protected Map formatImports(Map objs, String objsKey, String importKey) { - if (objs.containsKey(objsKey)) { - String modelName; - List> newImportList = new ArrayList>(); - - for (Map importMap : (List>) objs.get(objsKey)) { - modelName = ((String) importMap.get(importKey)).replace(modelPackage + ".", ""); - - if (reservedWords.contains(modelName)) { - continue; - } - - importMap.put(importKey, modelNamespace + "\\" + modelName); - newImportList.add(importMap); - } - - objs.put(objsKey, newImportList); - } - - return objs; - } +// @Override +// public Map postProcessModels(Map objs) { +// return addNamespaces(super.postProcessModels(objs)); +// } +// +// @Override +// public Map postProcessOperations(Map objs) { +// objs = addNamespaces(super.postProcessOperations(objs)); +// objs = formatImports(objs, "imports", "import"); +// +// return objs; +// } +// +// @Override +// public Map postProcessSupportingFileData(Map objs) { +// objs = addNamespaces(super.postProcessSupportingFileData(objs)); +// +// return objs; +// } +// +// protected Map addNamespaces(Map objs) { +// objs.put("rootNamespace", rootNamespace); +// objs.put("invokerNamespace", invokerNamespace); +// objs.put("apiNamespace", apiNamespace); +// objs.put("modelNamespace", modelNamespace); +// +// return objs; +// } +// +// protected Map formatImports(Map objs, String objsKey, String importKey) { +// if (objs.containsKey(objsKey)) { +// String modelName; +// List> newImportList = new ArrayList>(); +// +// for (Map importMap : (List>) objs.get(objsKey)) { +// modelName = ((String) importMap.get(importKey)).replace(modelPackage + ".", ""); +// +// if (reservedWords.contains(modelName)) { +// continue; +// } +// +// importMap.put(importKey, modelNamespace + "\\" + modelName); +// newImportList.add(importMap); +// } +// +// objs.put(objsKey, newImportList); +// } +// +// return objs; +// } } diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index b22c4e86a21..15726db05ea 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -15,7 +15,7 @@ * limitations under the License. */ -namespace {{invokerNamespace}}; +namespace {{invokerPackage}}; class ApiClient { @@ -77,7 +77,7 @@ class ApiClient { * @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 - * @throws \{{invokerNamespace}}\ApiException on a non 2xx response + * @throws \{{invokerPackage}}\ApiException on a non 2xx response * @return mixed */ public function callApi($resourcePath, $method, $queryParams, $postData, $headerParams) { diff --git a/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache b/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache index 79e7c8b356e..4880a8106d0 100644 --- a/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache @@ -1,5 +1,5 @@ Date: Mon, 22 Jun 2015 19:34:03 -0700 Subject: [PATCH 46/67] make packagePath configureable, and remove unused code --- .../codegen/languages/PhpClientCodegen.java | 73 +++---------------- 1 file changed, 11 insertions(+), 62 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 88e7725578c..54ae637d9a9 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -23,6 +23,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { protected String invokerPackage = "Swagger\\Client"; protected String groupId = "swagger"; protected String artifactId = "swagger-client"; + protected String packagePath = "SwaggerClient-php"; protected String artifactVersion = null; public PhpClientCodegen() { @@ -88,10 +89,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("DateTime", "\\DateTime"); cliOptions.add(new CliOption("invokerPackage", "namespace for core, non-api-specific classes")); + cliOptions.add(new CliOption("packagePath", "main package name for classes")); } public String getPackagePath() { - return "SwaggerClient-php"; + return packagePath; } public String toPackagePath(String packageName, String basePath) { @@ -129,6 +131,10 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { this.setInvokerPackage((String) additionalProperties.get("invokerPackage")); } + if (additionalProperties.containsKey("packagePath")) { + this.setPackagePath((String) additionalProperties.get("packagePath")); + } + supportingFiles.add(new SupportingFile("ApiClientConfiguration.mustache", toPackagePath(invokerPackage, "lib"), "ApiClientConfiguration.php")); supportingFiles.add(new SupportingFile("ApiClient.mustache", toPackagePath(invokerPackage, "lib"), "ApiClient.php")); supportingFiles.add(new SupportingFile("ApiException.mustache", toPackagePath(invokerPackage, "lib"), "ApiException.php")); @@ -137,16 +143,6 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php")); } -// protected String getSrcDir(String packageName) { -// return "src/" + packageName; -// } -// -// protected void prefixPackages() { -// setApiPackage(getSrcDir(apiPackage)); -// setInvokerPackage(getSrcDir(invokerPackage)); -// setModelPackage(getSrcDir(modelPackage)); -// } - @Override public String escapeReservedWord(String name) { return "_" + name; @@ -215,6 +211,10 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { this.invokerPackage = invokerPackage; } + public void setPackagePath(String packagePath) { + this.packagePath = packagePath; + } + @Override public String toVarName(String name) { // parameter name starting with number won't compile @@ -251,55 +251,4 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { // should be the same as the model name return toModelName(name); } - -// @Override -// public Map postProcessModels(Map objs) { -// return addNamespaces(super.postProcessModels(objs)); -// } -// -// @Override -// public Map postProcessOperations(Map objs) { -// objs = addNamespaces(super.postProcessOperations(objs)); -// objs = formatImports(objs, "imports", "import"); -// -// return objs; -// } -// -// @Override -// public Map postProcessSupportingFileData(Map objs) { -// objs = addNamespaces(super.postProcessSupportingFileData(objs)); -// -// return objs; -// } -// -// protected Map addNamespaces(Map objs) { -// objs.put("rootNamespace", rootNamespace); -// objs.put("invokerNamespace", invokerNamespace); -// objs.put("apiNamespace", apiNamespace); -// objs.put("modelNamespace", modelNamespace); -// -// return objs; -// } -// -// protected Map formatImports(Map objs, String objsKey, String importKey) { -// if (objs.containsKey(objsKey)) { -// String modelName; -// List> newImportList = new ArrayList>(); -// -// for (Map importMap : (List>) objs.get(objsKey)) { -// modelName = ((String) importMap.get(importKey)).replace(modelPackage + ".", ""); -// -// if (reservedWords.contains(modelName)) { -// continue; -// } -// -// importMap.put(importKey, modelNamespace + "\\" + modelName); -// newImportList.add(importMap); -// } -// -// objs.put(objsKey, newImportList); -// } -// -// return objs; -// } } From d5d148365630604177043da54bc18973339af1f2 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 20:14:54 -0700 Subject: [PATCH 47/67] properly account for custom and non-custom settings for modelPackage and apiPackage --- .../codegen/languages/PhpClientCodegen.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 54ae637d9a9..72fba6c54ce 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -33,8 +33,8 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { modelTemplateFiles.put("model.mustache", ".php"); apiTemplateFiles.put("api.mustache", ".php"); templateDir = "php"; - apiPackage = invokerPackage + "\\Api"; - modelPackage = invokerPackage + "\\Model"; + apiPackage = "Api"; + modelPackage = "Model"; reservedWords = new HashSet( Arrays.asList( @@ -88,7 +88,6 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("object", "object"); typeMapping.put("DateTime", "\\DateTime"); - cliOptions.add(new CliOption("invokerPackage", "namespace for core, non-api-specific classes")); cliOptions.add(new CliOption("packagePath", "main package name for classes")); } @@ -127,14 +126,22 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { public void processOpts() { super.processOpts(); - if (additionalProperties.containsKey("invokerPackage")) { - this.setInvokerPackage((String) additionalProperties.get("invokerPackage")); - } - if (additionalProperties.containsKey("packagePath")) { this.setPackagePath((String) additionalProperties.get("packagePath")); } + if (additionalProperties.containsKey("modelPackage")) { + this.setModelPackage(invokerPackage + "\\" + additionalProperties.get("modelPackage")); + } + + if (additionalProperties.containsKey("apiPackage")) { + this.setApiPackage(invokerPackage + "\\" + additionalProperties.get("apiPackage")); + } + + additionalProperties.replace("modelPackage", modelPackage); + additionalProperties.replace("apiPackage", apiPackage); + additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); + supportingFiles.add(new SupportingFile("ApiClientConfiguration.mustache", toPackagePath(invokerPackage, "lib"), "ApiClientConfiguration.php")); supportingFiles.add(new SupportingFile("ApiClient.mustache", toPackagePath(invokerPackage, "lib"), "ApiClient.php")); supportingFiles.add(new SupportingFile("ApiException.mustache", toPackagePath(invokerPackage, "lib"), "ApiException.php")); From c93b0dd3b80e9bd735e3c831f8dddbfc2a5020fa Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 20:24:19 -0700 Subject: [PATCH 48/67] make srcBasePath configureable --- .../codegen/languages/PhpClientCodegen.java | 24 ++++++++++++++----- .../src/main/resources/php/autoload.mustache | 4 ++-- .../src/main/resources/php/composer.mustache | 2 +- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 72fba6c54ce..71b0d67d215 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -25,6 +25,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { protected String artifactId = "swagger-client"; protected String packagePath = "SwaggerClient-php"; protected String artifactVersion = null; + protected String srcBasePath = "lib"; public PhpClientCodegen() { super(); @@ -44,6 +45,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put("modelPackage", modelPackage); additionalProperties.put("apiPackage", apiPackage); + additionalProperties.put("srcBasePath", srcBasePath); additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); additionalProperties.put("groupId", groupId); additionalProperties.put("artifactId", artifactId); @@ -89,6 +91,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("DateTime", "\\DateTime"); cliOptions.add(new CliOption("packagePath", "main package name for classes")); + cliOptions.add(new CliOption("srcBasePath", "directory directory under packagePath to serve as source root")); } public String getPackagePath() { @@ -130,6 +133,10 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { this.setPackagePath((String) additionalProperties.get("packagePath")); } + if (additionalProperties.containsKey("srcBasePath")) { + this.setSrcBasePath((String) additionalProperties.get("srcBasePath")); + } + if (additionalProperties.containsKey("modelPackage")) { this.setModelPackage(invokerPackage + "\\" + additionalProperties.get("modelPackage")); } @@ -138,14 +145,15 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { this.setApiPackage(invokerPackage + "\\" + additionalProperties.get("apiPackage")); } + additionalProperties.replace("srcBasePath", srcBasePath); additionalProperties.replace("modelPackage", modelPackage); additionalProperties.replace("apiPackage", apiPackage); additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); - supportingFiles.add(new SupportingFile("ApiClientConfiguration.mustache", toPackagePath(invokerPackage, "lib"), "ApiClientConfiguration.php")); - supportingFiles.add(new SupportingFile("ApiClient.mustache", toPackagePath(invokerPackage, "lib"), "ApiClient.php")); - supportingFiles.add(new SupportingFile("ApiException.mustache", toPackagePath(invokerPackage, "lib"), "ApiException.php")); - supportingFiles.add(new SupportingFile("ObjectSerializer.mustache", toPackagePath(invokerPackage, "lib"), "ObjectSerializer.php")); + supportingFiles.add(new SupportingFile("ApiClientConfiguration.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiClientConfiguration.php")); + supportingFiles.add(new SupportingFile("ApiClient.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiClient.php")); + supportingFiles.add(new SupportingFile("ApiException.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiException.php")); + supportingFiles.add(new SupportingFile("ObjectSerializer.mustache", toPackagePath(invokerPackage, srcBasePath), "ObjectSerializer.php")); supportingFiles.add(new SupportingFile("composer.mustache", getPackagePath(), "composer.json")); supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php")); } @@ -157,11 +165,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String apiFileFolder() { - return (outputFolder + "/" + toPackagePath(apiPackage(), "lib")); + return (outputFolder + "/" + toPackagePath(apiPackage(), srcBasePath)); } public String modelFileFolder() { - return (outputFolder + "/" + toPackagePath(modelPackage(), "lib")); + return (outputFolder + "/" + toPackagePath(modelPackage(), srcBasePath)); } @Override @@ -222,6 +230,10 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { this.packagePath = packagePath; } + public void setSrcBasePath(String srcBasePath) { + this.srcBasePath = srcBasePath; + } + @Override public String toVarName(String name) { // parameter name starting with number won't compile diff --git a/modules/swagger-codegen/src/main/resources/php/autoload.mustache b/modules/swagger-codegen/src/main/resources/php/autoload.mustache index 4f56a6e20c0..04be6e11992 100644 --- a/modules/swagger-codegen/src/main/resources/php/autoload.mustache +++ b/modules/swagger-codegen/src/main/resources/php/autoload.mustache @@ -4,7 +4,7 @@ * * After registering this autoload function with SPL, the following line * would cause the function to attempt to load the \{{invokerPackage}}\Baz\Qux class - * from /path/to/project/lib/Baz/Qux.php: + * from /path/to/project/{{srcBasePath}}/Baz/Qux.php: * * new \{{invokerPackage}}\Baz\Qux; * @@ -17,7 +17,7 @@ spl_autoload_register(function ($class) { $prefix = '{{escapedInvokerPackage}}\\'; // base directory for the namespace prefix - $base_dir = __DIR__ . '/lib/'; + $base_dir = __DIR__ . '/{{srcBasePath}}/'; // does the class use the namespace prefix? $len = strlen($prefix); diff --git a/modules/swagger-codegen/src/main/resources/php/composer.mustache b/modules/swagger-codegen/src/main/resources/php/composer.mustache index f4e38c84f73..d36267617c4 100644 --- a/modules/swagger-codegen/src/main/resources/php/composer.mustache +++ b/modules/swagger-codegen/src/main/resources/php/composer.mustache @@ -28,6 +28,6 @@ "squizlabs/php_codesniffer": "~2.0" }, "autoload": { - "psr-4": { "{{escapedInvokerPackage}}\\" : "lib/" } + "psr-4": { "{{escapedInvokerPackage}}\\" : "{{srcBasePath}}/" } } } From 8e0142338ecf63ff1cc84f635d8edb296e650aee Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 20:36:57 -0700 Subject: [PATCH 49/67] removing unused imports --- .../java/io/swagger/codegen/languages/PhpClientCodegen.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 71b0d67d215..7a67a6c3b34 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -11,13 +11,9 @@ import io.swagger.models.properties.Property; import io.swagger.models.properties.RefProperty; import java.io.File; -import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { protected String invokerPackage = "Swagger\\Client"; From 5a9e9550ca9a5701a222ca89f229082efa9c60de Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 20:43:00 -0700 Subject: [PATCH 50/67] fixing php-doc --- .../swagger-codegen/src/main/resources/php/ApiClient.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index 15726db05ea..e96961975d8 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -194,7 +194,7 @@ class ApiClient { /* * return the content type based on an array of content-type provided * - * @param array[string] content_type_array Array fo content-type + * @param string[] content_type_array Array fo content-type * @return string Content-Type (e.g. application/json) */ public static function selectHeaderContentType($content_type) { From 46ec934a9c065a3d4146f958d6cd171f72565002 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 20:49:12 -0700 Subject: [PATCH 51/67] java7 doesn't have replace, but put operates as such, so switch to that --- .../java/io/swagger/codegen/languages/PhpClientCodegen.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 7a67a6c3b34..9967980c53a 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -141,9 +141,9 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { this.setApiPackage(invokerPackage + "\\" + additionalProperties.get("apiPackage")); } - additionalProperties.replace("srcBasePath", srcBasePath); - additionalProperties.replace("modelPackage", modelPackage); - additionalProperties.replace("apiPackage", apiPackage); + additionalProperties.put("srcBasePath", srcBasePath); + additionalProperties.put("modelPackage", modelPackage); + additionalProperties.put("apiPackage", apiPackage); additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); supportingFiles.add(new SupportingFile("ApiClientConfiguration.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiClientConfiguration.php")); From 6623e120cd22d6f490b8003ca3fe5488e0c0063b Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 20:53:59 -0700 Subject: [PATCH 52/67] renaming to Configuration --- .../codegen/languages/PhpClientCodegen.java | 2 +- .../src/main/resources/php/ApiClient.mustache | 10 +- .../php/ApiClientConfiguration.mustache | 257 ------------------ .../src/main/resources/php/api.mustache | 2 +- .../main/resources/php/configuration.mustache | 232 +++++++++++++++- 5 files changed, 225 insertions(+), 278 deletions(-) delete mode 100644 modules/swagger-codegen/src/main/resources/php/ApiClientConfiguration.mustache diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 9967980c53a..550aa151f23 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -146,7 +146,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { additionalProperties.put("apiPackage", apiPackage); additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); - supportingFiles.add(new SupportingFile("ApiClientConfiguration.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiClientConfiguration.php")); + supportingFiles.add(new SupportingFile("configuration.mustache", toPackagePath(invokerPackage, srcBasePath), "Configuration.php")); supportingFiles.add(new SupportingFile("ApiClient.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiClient.php")); supportingFiles.add(new SupportingFile("ApiException.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiException.php")); supportingFiles.add(new SupportingFile("ObjectSerializer.mustache", toPackagePath(invokerPackage, srcBasePath), "ObjectSerializer.php")); diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index e96961975d8..488857c3a00 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -26,16 +26,16 @@ class ApiClient { public static $DELETE = "DELETE"; /** - * @var ApiClientConfiguration + * @var Configuration */ protected $config; /** - * @param ApiClientConfiguration $config config for this ApiClient + * @param Configuration $config config for this ApiClient */ - function __construct(ApiClientConfiguration $config = null) { + function __construct(Configuration $config = null) { if ($config == null) { - $config = ApiClientConfiguration::getDefaultConfiguration(); + $config = Configuration::getDefaultConfiguration(); } $this->config = $config; @@ -43,7 +43,7 @@ class ApiClient { /** * get the config - * @return ApiClientConfiguration + * @return Configuration */ public function getConfig() { return $this->config; diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClientConfiguration.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClientConfiguration.mustache deleted file mode 100644 index 491f5a45dd8..00000000000 --- a/modules/swagger-codegen/src/main/resources/php/ApiClientConfiguration.mustache +++ /dev/null @@ -1,257 +0,0 @@ -apiKeys[$key] = $value; - return $this; - } - - /** - * @param $key - * @return string - */ - public function getApiKey($key) { - return isset($this->apiKeys[$key]) ? $this->apiKeys[$key] : null; - } - - /** - * @param string $key - * @param string $value - * @return ApiClientConfiguration - */ - public function setApiKeyPrefix($key, $value) { - $this->apiKeyPrefixes[$key] = $value; - return $this; - } - - /** - * @param $key - * @return string - */ - public function getApiKeyPrefix($key) { - return isset($this->apiKeyPrefixes[$key]) ? $this->apiKeyPrefixes[$key] : null; - } - - /** - * @param string $username - * @return ApiClientConfiguration - */ - public function setUsername($username) { - $this->username = $username; - return $this; - } - - /** - * @return string - */ - public function getUsername() { - return $this->username; - } - - /** - * @param string $password - * @return ApiClientConfiguration - */ - public function setPassword($password) { - $this->password = $password; - return $this; - } - - /** - * @return string - */ - public function getPassword() { - return $this->password; - } - - /** - * add default header - * - * @param string $headerName header name (e.g. Token) - * @param string $headerValue header value (e.g. 1z8wp3) - * @return ApiClient - */ - public function addDefaultHeader($headerName, $headerValue) { - if (!is_string($headerName)) { - throw new \InvalidArgumentException('Header name must be a string.'); - } - - $this->defaultHeaders[$headerName] = $headerValue; - return $this; - } - - /** - * get the default header - * - * @return array default header - */ - public function getDefaultHeaders() { - return $this->defaultHeaders; - } - - /** - * @param string $host - * @return ApiClientConfiguration - */ - public function setHost($host) { - $this->host = $host; - return $this; - } - - /** - * @return string - */ - public function getHost() { - return $this->host; - } - - /** - * set the user agent of the api client - * - * @param string $userAgent the user agent of the api client - * @return ApiClient - */ - public function setUserAgent($userAgent) { - if (!is_string($userAgent)) { - throw new \InvalidArgumentException('User-agent must be a string.'); - } - - $this->userAgent = $userAgent; - return $this; - } - - /** - * get the user agent of the api client - * - * @return string user agent - */ - public function getUserAgent() { - return $this->userAgent; - } - - /** - * set the HTTP timeout value - * - * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] - * @return ApiClient - */ - public function setCurlTimeout($seconds) { - if (!is_numeric($seconds) || $seconds < 0) { - throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); - } - - $this->curlTimeout = $seconds; - return $this; - } - - /** - * get the HTTP timeout value - * - * @return string HTTP timeout value - */ - public function getCurlTimeout() { - return $this->curlTimeout; - } - - /** - * @param bool $debug - * @return ApiClientConfiguration - */ - public function setDebug($debug) { - $this->debug = $debug; - return $this; - } - - /** - * @return bool - */ - public function getDebug() { - return $this->debug; - } - - /** - * @param string $debugFile - * @return ApiClientConfiguration - */ - public function setDebugFile($debugFile) { - $this->debugFile = $debugFile; - return $this; - } - - /** - * @return string - */ - public function getDebugFile() { - return $this->debugFile; - } - - /** - * @return ApiClientConfiguration - */ - public static function getDefaultConfiguration() { - if (self::$defaultConfiguration == null) { - return new ApiClientConfiguration(); - } - - return self::$defaultConfiguration; - } - - public static function setDefaultConfiguration(ApiClientConfiguration $config) { - self::$defaultConfiguration = $config; - } -} diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index c9d21ca81b1..23f8f494aef 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -22,7 +22,7 @@ namespace {{apiPackage}}; -use \{{invokerPackage}}\ApiClientConfiguration; +use \{{invokerPackage}}\Configuration; use \{{invokerPackage}}\ApiClient; use \{{invokerPackage}}\ApiException; use \{{invokerPackage}}\ObjectSerializer; diff --git a/modules/swagger-codegen/src/main/resources/php/configuration.mustache b/modules/swagger-codegen/src/main/resources/php/configuration.mustache index 030910ffca7..a0cae318c2d 100644 --- a/modules/swagger-codegen/src/main/resources/php/configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/php/configuration.mustache @@ -17,37 +17,241 @@ namespace {{invokerPackage}}; -use \{{invokerPackage}}\ApiClient; - class Configuration { + private static $defaultConfiguration = null; + /** @var string[] Associate array to store API key(s) */ - public static $apiKey = array(); + protected $apiKeys = array(); /** string[] Associate array to store API prefix (e.g. Bearer) */ - public static $apiKeyPrefix = array(); + protected $apiKeyPrefixes = array(); /** @var string Username for HTTP basic authentication */ - public static $username = ''; + protected $username = ''; /** @var string Password for HTTP basic authentication */ - public static $password = ''; + protected $password = ''; /** @var \{{invokerPackage}}\ApiClient The default instance of ApiClient */ - public static $apiClient; + protected $defaultHeaders = array(); + + /** @var string The host */ + protected $host = 'http://localhost'; + + /** @var string timeout (second) of the HTTP request, by default set to 0, no timeout */ + protected $curlTimeout = 0; + + /** @var string user agent of the HTTP request, set to "PHP-Swagger" by default */ + protected $userAgent = "PHP-Swagger"; /** @var bool Debug switch (default set to false) */ - public static $debug = false; + protected $debug = false; /** @var string Debug file location (log to STDOUT by default) */ - public static $debug_file = 'php://output'; + protected $debugFile = 'php://output'; - /* - * manually initalize ApiClient + /** + * @param string $key + * @param string $value + * @return Configuration */ - public static function init() { - if (self::$apiClient === null) - self::$apiClient = new ApiClient(); + public function setApiKey($key, $value) { + $this->apiKeys[$key] = $value; + return $this; } + /** + * @param $key + * @return string + */ + public function getApiKey($key) { + return isset($this->apiKeys[$key]) ? $this->apiKeys[$key] : null; + } + + /** + * @param string $key + * @param string $value + * @return Configuration + */ + public function setApiKeyPrefix($key, $value) { + $this->apiKeyPrefixes[$key] = $value; + return $this; + } + + /** + * @param $key + * @return string + */ + public function getApiKeyPrefix($key) { + return isset($this->apiKeyPrefixes[$key]) ? $this->apiKeyPrefixes[$key] : null; + } + + /** + * @param string $username + * @return Configuration + */ + public function setUsername($username) { + $this->username = $username; + return $this; + } + + /** + * @return string + */ + public function getUsername() { + return $this->username; + } + + /** + * @param string $password + * @return Configuration + */ + public function setPassword($password) { + $this->password = $password; + return $this; + } + + /** + * @return string + */ + public function getPassword() { + return $this->password; + } + + /** + * add default header + * + * @param string $headerName header name (e.g. Token) + * @param string $headerValue header value (e.g. 1z8wp3) + * @return ApiClient + */ + public function addDefaultHeader($headerName, $headerValue) { + if (!is_string($headerName)) { + throw new \InvalidArgumentException('Header name must be a string.'); + } + + $this->defaultHeaders[$headerName] = $headerValue; + return $this; + } + + /** + * get the default header + * + * @return array default header + */ + public function getDefaultHeaders() { + return $this->defaultHeaders; + } + + /** + * @param string $host + * @return Configuration + */ + public function setHost($host) { + $this->host = $host; + return $this; + } + + /** + * @return string + */ + public function getHost() { + return $this->host; + } + + /** + * set the user agent of the api client + * + * @param string $userAgent the user agent of the api client + * @return ApiClient + */ + public function setUserAgent($userAgent) { + if (!is_string($userAgent)) { + throw new \InvalidArgumentException('User-agent must be a string.'); + } + + $this->userAgent = $userAgent; + return $this; + } + + /** + * get the user agent of the api client + * + * @return string user agent + */ + public function getUserAgent() { + return $this->userAgent; + } + + /** + * set the HTTP timeout value + * + * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] + * @return ApiClient + */ + public function setCurlTimeout($seconds) { + if (!is_numeric($seconds) || $seconds < 0) { + throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); + } + + $this->curlTimeout = $seconds; + return $this; + } + + /** + * get the HTTP timeout value + * + * @return string HTTP timeout value + */ + public function getCurlTimeout() { + return $this->curlTimeout; + } + + /** + * @param bool $debug + * @return Configuration + */ + public function setDebug($debug) { + $this->debug = $debug; + return $this; + } + + /** + * @return bool + */ + public function getDebug() { + return $this->debug; + } + + /** + * @param string $debugFile + * @return Configuration + */ + public function setDebugFile($debugFile) { + $this->debugFile = $debugFile; + return $this; + } + + /** + * @return string + */ + public function getDebugFile() { + return $this->debugFile; + } + + /** + * @return Configuration + */ + public static function getDefaultConfiguration() { + if (self::$defaultConfiguration == null) { + return new Configuration(); + } + + return self::$defaultConfiguration; + } + + public static function setDefaultConfiguration(Configuration $config) { + self::$defaultConfiguration = $config; + } } From 60b0ffeb0eeb93b47bc82372f2d3204bcd5b5110 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 21:06:22 -0700 Subject: [PATCH 53/67] don't prepend the invokerPackage - an artifact from an earlier implementation --- .../io/swagger/codegen/languages/PhpClientCodegen.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 550aa151f23..20e8d20c5ed 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -30,8 +30,8 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { modelTemplateFiles.put("model.mustache", ".php"); apiTemplateFiles.put("api.mustache", ".php"); templateDir = "php"; - apiPackage = "Api"; - modelPackage = "Model"; + apiPackage = invokerPackage + "\\Api"; + modelPackage = invokerPackage + "\\Model"; reservedWords = new HashSet( Arrays.asList( @@ -134,11 +134,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { } if (additionalProperties.containsKey("modelPackage")) { - this.setModelPackage(invokerPackage + "\\" + additionalProperties.get("modelPackage")); + this.setModelPackage((String) additionalProperties.get("modelPackage")); } if (additionalProperties.containsKey("apiPackage")) { - this.setApiPackage(invokerPackage + "\\" + additionalProperties.get("apiPackage")); + this.setApiPackage((String) additionalProperties.get("apiPackage")); } additionalProperties.put("srcBasePath", srcBasePath); From 2fced0f6342a4594c2f8a000cef9f266a2e68d66 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 21:12:13 -0700 Subject: [PATCH 54/67] Revert "Updates to csharp model template to support inheritance" This reverts commit 5f1df9e093eaf7b584c98879b4e05dcf1ac8c58f. --- .../src/main/resources/csharp/model.mustache | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/csharp/model.mustache b/modules/swagger-codegen/src/main/resources/csharp/model.mustache index 111c98993a2..ce0e62de192 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/model.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/model.mustache @@ -13,7 +13,7 @@ namespace {{package}} { /// {{description}} /// [DataContract] - public class {{classname}}{{#parent}} : {{{parent}}}{{/parent}} { + public class {{classname}} { {{#vars}} {{#description}}/* {{{description}}} */{{/description}} [DataMember(Name="{{baseName}}", EmitDefaultValue=false)] @@ -39,11 +39,11 @@ namespace {{package}} { /// Get the JSON string presentation of the object /// /// JSON string presentation of the object - public {{#parent}} new {{/parent}}string ToJson() { + public string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } } {{/model}} {{/models}} -} \ No newline at end of file +} From c91a1b963bb8548f807ecbfe8b22c1e27f8f9a8a Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Mon, 22 Jun 2015 21:33:44 -0700 Subject: [PATCH 55/67] change serializer to be instanced, rather than static methods --- .../src/main/resources/php/ApiClient.mustache | 18 ++++++++--- .../resources/php/ObjectSerializer.mustache | 32 +++++++++---------- .../src/main/resources/php/api.mustache | 12 +++---- 3 files changed, 36 insertions(+), 26 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index 488857c3a00..2862a0e0538 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -25,11 +25,12 @@ class ApiClient { public static $PUT = "PUT"; public static $DELETE = "DELETE"; - /** - * @var Configuration - */ + /** @var Configuration */ protected $config; + /** @var ObjectSerializer */ + protected $serializer; + /** * @param Configuration $config config for this ApiClient */ @@ -39,6 +40,7 @@ class ApiClient { } $this->config = $config; + $this->serializer = new ObjectSerializer(); } /** @@ -49,6 +51,14 @@ class ApiClient { return $this->config; } + /** + * get the serializer + * @return ObjectSerializer + */ + public function getSerializer() { + return $this->serializer; + } + /** * Get API key (with prefix if set) * @param string $apiKey name of apikey @@ -96,7 +106,7 @@ class ApiClient { $postData = http_build_query($postData); } else if ((is_object($postData) or is_array($postData)) and !in_array('Content-Type: multipart/form-data', $headers)) { // json model - $postData = json_encode(ObjectSerializer::sanitizeForSerialization($postData)); + $postData = json_encode($this->serializer->sanitizeForSerialization($postData)); } $url = $this->config->getHost() . $resourcePath; diff --git a/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache b/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache index 4880a8106d0..56a61e97c91 100644 --- a/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache @@ -8,14 +8,14 @@ class ObjectSerializer { * @param mixed $data the data to serialize * @return string serialized form of $data */ - public static function sanitizeForSerialization($data) { + public 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] = self::sanitizeForSerialization($value); + $data[$property] = $this->sanitizeForSerialization($value); } $sanitized = $data; } else if (is_object($data)) { @@ -23,7 +23,7 @@ class ObjectSerializer { foreach (array_keys($data::$swaggerTypes) as $property) { $getter = $data::$getters[$property]; if ($data->$getter() !== null) { - $values[$data::$attributeMap[$property]] = self::sanitizeForSerialization($data->$getter()); + $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$getter()); } } $sanitized = $values; @@ -40,8 +40,8 @@ class ObjectSerializer { * @param string $value a string which will be part of the path * @return string the serialized object */ - public static function toPathValue($value) { - return rawurlencode(self::toString($value)); + public function toPathValue($value) { + return rawurlencode($this->toString($value)); } /** @@ -52,11 +52,11 @@ class ObjectSerializer { * @param object $object an object to be serialized to a string * @return string the serialized object */ - public static function toQueryValue($object) { + public function toQueryValue($object) { if (is_array($object)) { return implode(',', $object); } else { - return self::toString($object); + return $this->toString($object); } } @@ -67,8 +67,8 @@ class ObjectSerializer { * @param string $value a string which will be part of the header * @return string the header string */ - public static function toHeaderValue($value) { - return self::toString($value); + public function toHeaderValue($value) { + return $this->toString($value); } /** @@ -78,8 +78,8 @@ class ObjectSerializer { * @param string $value the value of the form parameter * @return string the form string */ - public static function toFormValue($value) { - return self::toString($value); + public function toFormValue($value) { + return $this->toString($value); } /** @@ -89,7 +89,7 @@ class ObjectSerializer { * @param string $value the value of the parameter * @return string the header string */ - public static function toString($value) { + public function toString($value) { if ($value instanceof \DateTime) { // datetime in ISO8601 format return $value->format(\DateTime::ISO8601); } else { @@ -104,7 +104,7 @@ class ObjectSerializer { * @param string $class class name is passed as a string * @return object an instance of $class */ - public static function deserialize($data, $class) { + public function deserialize($data, $class) { if (null === $data) { $deserialized = null; } elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] @@ -114,14 +114,14 @@ class ObjectSerializer { $subClass_array = explode(',', $inner, 2); $subClass = $subClass_array[1]; foreach ($data as $key => $value) { - $deserialized[$key] = self::deserialize($value, $subClass); + $deserialized[$key] = $this->deserialize($value, $subClass); } } } elseif (strcasecmp(substr($class, -2),'[]') == 0) { $subClass = substr($class, 0, -2); $values = array(); foreach ($data as $key => $value) { - $values[] = self::deserialize($value, $subClass); + $values[] = $this->deserialize($value, $subClass); } $deserialized = $values; } elseif ($class == 'DateTime') { @@ -140,7 +140,7 @@ class ObjectSerializer { $propertyValue = $data->{$instance::$attributeMap[$property]}; if (isset($propertyValue)) { - $instance->$propertySetter(self::deserialize($propertyValue, $type)); + $instance->$propertySetter($this->deserialize($propertyValue, $type)); } } $deserialized = $instance; diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 23f8f494aef..cd483ffa881 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -95,21 +95,21 @@ class {{classname}} { {{#queryParams}}// query params if(${{paramName}} !== null) { - $queryParams['{{baseName}}'] = ObjectSerializer::toQueryValue(${{paramName}}); + $queryParams['{{baseName}}'] = $this->apiClient->getSerializer()->toQueryValue(${{paramName}}); }{{/queryParams}} {{#headerParams}}// header params if(${{paramName}} !== null) { - $headerParams['{{baseName}}'] = ObjectSerializer::toHeaderValue(${{paramName}}); + $headerParams['{{baseName}}'] = $this->apiClient->getSerializer()->toHeaderValue(${{paramName}}); }{{/headerParams}} {{#pathParams}}// path params if(${{paramName}} !== null) { $resourcePath = str_replace("{" . "{{baseName}}" . "}", - ObjectSerializer::toPathValue(${{paramName}}), + $this->apiClient->getSerializer()->toPathValue(${{paramName}}), $resourcePath); }{{/pathParams}} {{#formParams}}// form params if (${{paramName}} !== null) { - $formParams['{{baseName}}'] = {{#isFile}}'@' . {{/isFile}}ObjectSerializer::toFormValue(${{paramName}}); + $formParams['{{baseName}}'] = {{#isFile}}'@' . {{/isFile}}$this->apiClient->getSerializer()->toFormValue(${{paramName}}); }{{/formParams}} {{#bodyParams}}// body params $_tempBody = null; @@ -140,7 +140,7 @@ class {{classname}} { } catch (ApiException $e) { switch ($e->getCode()) { {{#responses}}{{#dataType}} case {{code}}: - $data = ObjectSerializer::deserialize($e->getResponseBody(), '{{dataType}}'); + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '{{dataType}}'); $e->setResponseObject($data); break;{{/dataType}}{{/responses}} } @@ -152,7 +152,7 @@ class {{classname}} { return null; } - $responseObject = ObjectSerializer::deserialize($response,'{{returnType}}'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'{{returnType}}'); return $responseObject; {{/returnType}} } From c45af23946779a88444dab5a9795a19a41accbe5 Mon Sep 17 00:00:00 2001 From: Martin Hardorf Date: Tue, 23 Jun 2015 12:05:43 +0200 Subject: [PATCH 56/67] Fixed headerParams and paramName --- .../src/main/resources/TypeScript-Angular/api.mustache | 8 ++++---- .../src/main/resources/TypeScript-node/api.mustache | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache index 1095667b245..1bc4a8a02a1 100644 --- a/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache +++ b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache @@ -22,13 +22,13 @@ module {{package}} { } } {{#operation}} - public {{nickname}} ({{#allParams}}{{paramName}}: {{{dataType}}}, {{/allParams}} extraHttpRequestParams?: any ) : ng.IHttpPromise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}{}{{/returnType}}> { + public {{nickname}} ({{#allParams}}{{paramName}}: {{{dataType}}}{{#hasMore}}, {{/hasMore}} {{/allParams}} extraHttpRequestParams?: any ) : ng.IHttpPromise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}{}{{/returnType}}> { var path = this.basePath + '{{path}}'; {{#pathParams}} path = path.replace('{' + '{{paramName}}' + '}', String({{paramName}})); {{/pathParams}} var queryParameters: any = {}; - var headers: any = {}; + var headerParams: any = {}; {{#allParams}}{{#required}} // verify required parameter '{{paramName}}' is set if (!{{paramName}}) { @@ -43,10 +43,10 @@ module {{package}} { method: '{{httpMethod}}', url: path, json: true, - {{#bodyParam}}data: body, + {{#bodyParam}}data: {{paramName}}, {{/bodyParam}} params: queryParameters, - headers: headers + headers: headerParams }; if (extraHttpRequestParams) { diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache index 156ad63f72d..eb569cdc928 100644 --- a/modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache +++ b/modules/swagger-codegen/src/main/resources/TypeScript-node/api.mustache @@ -24,7 +24,7 @@ export class {{classname}} { {{/pathParams}} var queryParameters: any = {}; - var headers: any = {}; + var headerParams: any = {}; {{#allParams}}{{#required}} // verify required parameter '{{paramName}}' is set @@ -48,7 +48,7 @@ export class {{classname}} { qs: queryParameters, uri: path, json: true, - {{#bodyParam}}body: body, + {{#bodyParam}}body: {{paramName}}, {{/bodyParam}} auth: { username: this.username, password: this.password From 550493ba848a9de97a55ac093522f1d3929a686a Mon Sep 17 00:00:00 2001 From: wing328 Date: Tue, 23 Jun 2015 21:20:12 +0800 Subject: [PATCH 57/67] fix php separator --- .../java/io/swagger/codegen/languages/PhpClientCodegen.java | 6 +++--- .../petstore/php/SwaggerClient-php/lib/Api/PetApi.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 0690163f137..9ed02361dff 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -23,7 +23,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { public PhpClientCodegen() { super(); - outputFolder = "generated-code/php"; + outputFolder = "generated-code" + File.separator + "php"; modelTemplateFiles.put("model.mustache", ".php"); apiTemplateFiles.put("api.mustache", ".php"); templateDir = "php"; @@ -127,11 +127,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String apiFileFolder() { - return (outputFolder + "/" + toPackagePath(apiPackage(), "lib")); + return (outputFolder + File.separator + toPackagePath(apiPackage(), "lib")); } public String modelFileFolder() { - return (outputFolder + "/" + toPackagePath(modelPackage(), "lib")); + return (outputFolder + File.separator + toPackagePath(modelPackage(), "lib")); } @Override diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php b/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php index f4f6ea8538a..7fe7b70312e 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php @@ -516,7 +516,7 @@ class PetApi { $formParams['additionalMetadata'] = $this->apiClient->toFormValue($additional_metadata); }// form params if ($file !== null) { - $formParams['file'] = '@' . $this->apiClient->toFormValue($file); + $formParams['file'] = '@'.$this->apiClient->toFormValue($file); } From 13d350be2e37c2d6fc0c04236d7f5961870240c6 Mon Sep 17 00:00:00 2001 From: xhh Date: Tue, 23 Jun 2015 21:23:48 +0800 Subject: [PATCH 58/67] Fix warnings and upgrade jersey for Scala client * Upgrade jersey to latest version (from 1.7 to 1.19) * Replace getClientResponseStatus() with getStatusInfo() * Fix the following maven warnings and model import warnings [WARNING] 'build.plugins.plugin.version' for org.codehaus.mojo:build-helper-maven-plugin is missing. @ line 72, column 15 [WARNING] Using platform encoding (UTF-8 actually) to copy filtered resources, i.e. build is platform dependent! [WARNING] Expected all dependencies to require Scala version: 2.10.4 [WARNING] com.fasterxml.jackson.module:jackson-module-scala_2.10:2.4.2 requires scala version: 2.10.4 [WARNING] org.scala-lang:scala-reflect:2.10.4 requires scala version: 2.10.4 [WARNING] io.swagger:swagger-scala-client:1.0.0 requires scala version: 2.10.4 [WARNING] org.scalatest:scalatest_2.10:2.1.3 requires scala version: 2.10.3 [WARNING] Multiple versions of scala libraries detected! [WARNING] /Users/xhh/projects/swagger-codegen/samples/client/petstore/scala/src/main/scala/io/swagger/client/model/Pet.scala:3: warning: imported `Category' is permanently hidden by definition of object Category in package model --- .../codegen/languages/ScalaClientCodegen.java | 16 ++++++++++++++++ .../src/main/resources/scala/apiInvoker.mustache | 7 +++---- .../src/main/resources/scala/pom.mustache | 7 +++++-- samples/client/petstore/scala/pom.xml | 7 +++++-- .../scala/io/swagger/client/ApiInvoker.scala | 7 +++---- .../main/scala/io/swagger/client/model/Pet.scala | 2 -- 6 files changed, 32 insertions(+), 14 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ScalaClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ScalaClientCodegen.java index d8c143aad1d..6ad296a0210 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ScalaClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/ScalaClientCodegen.java @@ -20,6 +20,9 @@ import java.io.File; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig { protected String invokerPackage = "io.swagger.client"; @@ -214,4 +217,17 @@ public class ScalaClientCodegen extends DefaultCodegen implements CodegenConfig return camelize(operationId, true); } + @Override + public Map postProcessModels(Map objs) { + // remove model imports to avoid warnings for importing class in the same package in Scala + List> imports = (List>) objs.get("imports"); + final String prefix = modelPackage() + "."; + Iterator> iterator = imports.iterator(); + while (iterator.hasNext()) { + String _import = iterator.next().get("import"); + if (_import.startsWith(prefix)) iterator.remove(); + } + return objs; + } + } diff --git a/modules/swagger-codegen/src/main/resources/scala/apiInvoker.mustache b/modules/swagger-codegen/src/main/resources/scala/apiInvoker.mustache index f432c2dc59e..9c2e9c073cd 100644 --- a/modules/swagger-codegen/src/main/resources/scala/apiInvoker.mustache +++ b/modules/swagger-codegen/src/main/resources/scala/apiInvoker.mustache @@ -141,7 +141,7 @@ class ApiInvoker(val mapper: ObjectMapper = ScalaJsonUtil.getJsonMapper, } case _ => null } - response.getClientResponseStatus().getStatusCode() match { + response.getStatusInfo().getStatusCode() match { case 204 => "" case code: Int if (Range(200, 299).contains(code)) => { response.hasEntity() match { @@ -155,7 +155,7 @@ class ApiInvoker(val mapper: ObjectMapper = ScalaJsonUtil.getJsonMapper, case false => "no data" } throw new ApiException( - response.getClientResponseStatus().getStatusCode(), + response.getStatusInfo().getStatusCode(), entity) } } @@ -172,7 +172,7 @@ class ApiInvoker(val mapper: ObjectMapper = ScalaJsonUtil.getJsonMapper, } } } - + def newClient(host: String): Client = asyncHttpClient match { case true => { import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig @@ -200,4 +200,3 @@ object ApiInvoker extends ApiInvoker(mapper = ScalaJsonUtil.getJsonMapper, authPreemptive = {{authPreemptive}}) class ApiException(val code: Int, msg: String) extends RuntimeException(msg) - diff --git a/modules/swagger-codegen/src/main/resources/scala/pom.mustache b/modules/swagger-codegen/src/main/resources/scala/pom.mustache index 2d8a1257eb4..c6fe4a1f356 100644 --- a/modules/swagger-codegen/src/main/resources/scala/pom.mustache +++ b/modules/swagger-codegen/src/main/resources/scala/pom.mustache @@ -72,6 +72,7 @@ org.codehaus.mojo build-helper-maven-plugin + 1.9.1 add_sources @@ -208,7 +209,7 @@ 2.10.4 1.2 2.2 - 1.7 + 1.19 1.5.0 1.0.5 1.0.0 @@ -216,6 +217,8 @@ 4.8.1 3.1.5 - 2.1.3 + 2.2.4 + + UTF-8 diff --git a/samples/client/petstore/scala/pom.xml b/samples/client/petstore/scala/pom.xml index 7e56a41c890..9f39f4e45ce 100644 --- a/samples/client/petstore/scala/pom.xml +++ b/samples/client/petstore/scala/pom.xml @@ -72,6 +72,7 @@ org.codehaus.mojo build-helper-maven-plugin + 1.9.1 add_sources @@ -208,7 +209,7 @@ 2.10.4 1.2 2.2 - 1.7 + 1.19 1.5.0 1.0.5 1.0.0 @@ -216,6 +217,8 @@ 4.8.1 3.1.5 - 2.1.3 + 2.2.4 + + UTF-8 diff --git a/samples/client/petstore/scala/src/main/scala/io/swagger/client/ApiInvoker.scala b/samples/client/petstore/scala/src/main/scala/io/swagger/client/ApiInvoker.scala index 91ab98471e9..1f9d3c012d5 100644 --- a/samples/client/petstore/scala/src/main/scala/io/swagger/client/ApiInvoker.scala +++ b/samples/client/petstore/scala/src/main/scala/io/swagger/client/ApiInvoker.scala @@ -141,7 +141,7 @@ class ApiInvoker(val mapper: ObjectMapper = ScalaJsonUtil.getJsonMapper, } case _ => null } - response.getClientResponseStatus().getStatusCode() match { + response.getStatusInfo().getStatusCode() match { case 204 => "" case code: Int if (Range(200, 299).contains(code)) => { response.hasEntity() match { @@ -155,7 +155,7 @@ class ApiInvoker(val mapper: ObjectMapper = ScalaJsonUtil.getJsonMapper, case false => "no data" } throw new ApiException( - response.getClientResponseStatus().getStatusCode(), + response.getStatusInfo().getStatusCode(), entity) } } @@ -172,7 +172,7 @@ class ApiInvoker(val mapper: ObjectMapper = ScalaJsonUtil.getJsonMapper, } } } - + def newClient(host: String): Client = asyncHttpClient match { case true => { import org.sonatype.spice.jersey.client.ahc.config.DefaultAhcConfig @@ -200,4 +200,3 @@ object ApiInvoker extends ApiInvoker(mapper = ScalaJsonUtil.getJsonMapper, authPreemptive = false) class ApiException(val code: Int, msg: String) extends RuntimeException(msg) - diff --git a/samples/client/petstore/scala/src/main/scala/io/swagger/client/model/Pet.scala b/samples/client/petstore/scala/src/main/scala/io/swagger/client/model/Pet.scala index 430f6a3659c..30dc8750976 100644 --- a/samples/client/petstore/scala/src/main/scala/io/swagger/client/model/Pet.scala +++ b/samples/client/petstore/scala/src/main/scala/io/swagger/client/model/Pet.scala @@ -1,7 +1,5 @@ package io.swagger.client.model -import io.swagger.client.model.Category -import io.swagger.client.model.Tag From 2fce2e410937a89cb35ac910a15dd1422d601171 Mon Sep 17 00:00:00 2001 From: Martin Hardorf Date: Tue, 23 Jun 2015 15:37:07 +0200 Subject: [PATCH 59/67] Removed wrong hasMore from Angular TypeScript mustache --- .../src/main/resources/TypeScript-Angular/api.mustache | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache index 1bc4a8a02a1..88f7f9ff15a 100644 --- a/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache +++ b/modules/swagger-codegen/src/main/resources/TypeScript-Angular/api.mustache @@ -22,7 +22,7 @@ module {{package}} { } } {{#operation}} - public {{nickname}} ({{#allParams}}{{paramName}}: {{{dataType}}}{{#hasMore}}, {{/hasMore}} {{/allParams}} extraHttpRequestParams?: any ) : ng.IHttpPromise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}{}{{/returnType}}> { + public {{nickname}} ({{#allParams}}{{paramName}}: {{{dataType}}}, {{/allParams}} extraHttpRequestParams?: any ) : ng.IHttpPromise<{{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}{}{{/returnType}}> { var path = this.basePath + '{{path}}'; {{#pathParams}} path = path.replace('{' + '{{paramName}}' + '}', String({{paramName}})); From 2979d938292fb5add41b98f520f05778755a713b Mon Sep 17 00:00:00 2001 From: wing328 Date: Tue, 23 Jun 2015 21:47:10 +0800 Subject: [PATCH 60/67] use replace instead of replaceAll --- .../io/swagger/codegen/languages/PhpClientCodegen.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 9ed02361dff..57fb52137e1 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -101,11 +101,12 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { return (getPackagePath() + File.separatorChar + basePath // Replace period, backslash, forward slash with file separator in package name - + packageName.replaceAll("[\\.\\\\/]", File.separator) + + packageName.replace("\\", File.separator). + replace(".", File.separator).replace("/", File.separator) // Trim prefix file separators from package path .replaceAll("^" + File.separator, "")) - // Trim trailing file separators from the overall path - .replaceAll(File.separator + "$", ""); + // Trim trailing file separators from the overall path + .replaceAll(File.separator + "$", ""); } public CodegenType getTag() { From 351833a923dc5a21e3c4f8fba50b7e008c908ec3 Mon Sep 17 00:00:00 2001 From: wing328 Date: Tue, 23 Jun 2015 21:52:00 +0800 Subject: [PATCH 61/67] test fix --- .../java/io/swagger/codegen/languages/PhpClientCodegen.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 57fb52137e1..e504a888f8a 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -102,11 +102,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { return (getPackagePath() + File.separatorChar + basePath // Replace period, backslash, forward slash with file separator in package name + packageName.replace("\\", File.separator). - replace(".", File.separator).replace("/", File.separator) + replace(".", File.separator).replace("/", File.separator)); // Trim prefix file separators from package path - .replaceAll("^" + File.separator, "")) + //.replaceAll("^" + File.separator, "")) // Trim trailing file separators from the overall path - .replaceAll(File.separator + "$", ""); + //.replaceAll(File.separator + "$", ""); } public CodegenType getTag() { From d18426c69a85500f71bc5b0b7d1e62162aeefbfd Mon Sep 17 00:00:00 2001 From: wing328 Date: Tue, 23 Jun 2015 22:30:43 +0800 Subject: [PATCH 62/67] fix reg expression --- .../codegen/languages/PhpClientCodegen.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index e504a888f8a..7f92a06fe76 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -99,14 +99,20 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { basePath = basePath.replaceAll("[\\\\/]?$", "") + File.separatorChar; } + String regFirstPathSeparator; + if ("/".equals(File.separator)) { // for mac, linux + regFirstPathSeparator = "^/"; + } else { // for windows + regFirstPathSeparator = "^\\"; + } + return (getPackagePath() + File.separatorChar + basePath // Replace period, backslash, forward slash with file separator in package name - + packageName.replace("\\", File.separator). - replace(".", File.separator).replace("/", File.separator)); + + packageName.replaceAll("[\\.\\\\/]", File.separator) // Trim prefix file separators from package path - //.replaceAll("^" + File.separator, "")) + .replaceAll(regFirstPathSeparator, "")) // Trim trailing file separators from the overall path - //.replaceAll(File.separator + "$", ""); + .replaceAll(File.separator + "$", ""); } public CodegenType getTag() { From d83036ccdfacd31aa7c2eefab66333b4bbf79c73 Mon Sep 17 00:00:00 2001 From: wing328 Date: Tue, 23 Jun 2015 22:36:57 +0800 Subject: [PATCH 63/67] fix regular expression --- .../swagger/codegen/languages/PhpClientCodegen.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 7f92a06fe76..5bf8400577d 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -103,7 +103,14 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { if ("/".equals(File.separator)) { // for mac, linux regFirstPathSeparator = "^/"; } else { // for windows - regFirstPathSeparator = "^\\"; + regFirstPathSeparator = "^\\\\"; + } + + String regLastPathSeparator; + if ("/".equals(File.separator)) { // for mac, linux + regLastPathSeparator = "/$"; + } else { // for windows + regLastPathSeparator = "\\\\$"; } return (getPackagePath() + File.separatorChar + basePath @@ -112,7 +119,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { // Trim prefix file separators from package path .replaceAll(regFirstPathSeparator, "")) // Trim trailing file separators from the overall path - .replaceAll(File.separator + "$", ""); + .replaceAll(regLastPathSeparator+ "$", ""); } public CodegenType getTag() { From 1b4c71c28039ead9f656f4afe22b70d635470ffe Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Tue, 23 Jun 2015 09:27:34 -0700 Subject: [PATCH 64/67] re-adding Configuration->deleteDefaultHeader --- .../src/main/resources/php/configuration.mustache | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/modules/swagger-codegen/src/main/resources/php/configuration.mustache b/modules/swagger-codegen/src/main/resources/php/configuration.mustache index a0cae318c2d..b85ad289418 100644 --- a/modules/swagger-codegen/src/main/resources/php/configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/php/configuration.mustache @@ -144,6 +144,15 @@ class Configuration { return $this->defaultHeaders; } + /** + * delete a default header + * @param string $headerName the header to delete + * @return Configuration + */ + public function deleteDefaultHeader($headerName) { + unset($this->defaultHeaders[$headerName]); + } + /** * @param string $host * @return Configuration From efd5b806be552c973594fb95622d1114922d02b2 Mon Sep 17 00:00:00 2001 From: nmonterroso Date: Tue, 23 Jun 2015 09:27:52 -0700 Subject: [PATCH 65/67] updating php generated samples and updating tests --- .../php/SwaggerClient-php/lib/Api/PetApi.php | 310 +++++++++++------ .../SwaggerClient-php/lib/Api/StoreApi.php | 174 ++++++---- .../php/SwaggerClient-php/lib/Api/UserApi.php | 256 ++++++++------ .../php/SwaggerClient-php/lib/ApiClient.php | 327 +++--------------- .../SwaggerClient-php/lib/ApiException.php | 28 +- .../SwaggerClient-php/lib/Configuration.php | 241 ++++++++++++- .../SwaggerClient-php/lib/Model/Category.php | 60 +++- .../php/SwaggerClient-php/lib/Model/Order.php | 156 ++++++++- .../php/SwaggerClient-php/lib/Model/Pet.php | 156 ++++++++- .../php/SwaggerClient-php/lib/Model/Tag.php | 60 +++- .../php/SwaggerClient-php/lib/Model/User.php | 204 ++++++++++- .../lib/ObjectSerializer.php | 151 ++++++++ .../SwaggerClient-php/tests/PetApiTest.php | 104 +++--- .../SwaggerClient-php/tests/StoreApiTest.php | 7 +- .../SwaggerClient-php/tests/UserApiTest.php | 7 +- 15 files changed, 1549 insertions(+), 692 deletions(-) create mode 100644 samples/client/petstore/php/SwaggerClient-php/lib/ObjectSerializer.php diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php b/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php index f4f6ea8538a..e6d8fcd2c8c 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php @@ -22,30 +22,28 @@ namespace Swagger\Client\Api; -use \Swagger\Client\ApiClient; use \Swagger\Client\Configuration; +use \Swagger\Client\ApiClient; +use \Swagger\Client\ApiException; +use \Swagger\Client\ObjectSerializer; class PetApi { - /** - * @param \Swagger\Client\ApiClient|null $apiClient The api client to use. Defaults to getting it from Configuration - */ - function __construct($apiClient = null) { - if (null === $apiClient) { - if (Configuration::$apiClient === null) { - Configuration::$apiClient = new ApiClient(); // create a new API client if not present - $this->apiClient = Configuration::$apiClient; - } - else - $this->apiClient = Configuration::$apiClient; // use the default one - } else { - $this->apiClient = $apiClient; // use the one provided by the user - } - } - /** @var \Swagger\Client\ApiClient instance of the ApiClient */ private $apiClient; + /** + * @param \Swagger\Client\ApiClient|null $apiClient The api client to use + */ + function __construct($apiClient = null) { + if ($apiClient == null) { + $apiClient = new ApiClient(); + $apiClient->getConfig()->setHost('http://petstore.swagger.io/v2'); + } + + $this->apiClient = $apiClient; + } + /** * @return \Swagger\Client\ApiClient get the API client */ @@ -54,10 +52,12 @@ class PetApi { } /** - * @param \Swagger\Client $apiClient set the API client + * @param \Swagger\Client\ApiClient $apiClient set the API client + * @return PetApi */ - public function setApiClient($apiClient) { + public function setApiClient(ApiClient $apiClient) { $this->apiClient = $apiClient; + return $this; } @@ -68,6 +68,7 @@ class PetApi { * * @param \Swagger\Client\Model\Pet $body Pet object that needs to be added to the store (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function updatePet($body) { @@ -80,11 +81,11 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json','application/xml')); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array('application/json','application/xml')); @@ -103,14 +104,21 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -121,6 +129,7 @@ class PetApi { * * @param \Swagger\Client\Model\Pet $body Pet object that needs to be added to the store (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function addPet($body) { @@ -133,11 +142,11 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json','application/xml')); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array('application/json','application/xml')); @@ -156,14 +165,21 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -174,6 +190,7 @@ class PetApi { * * @param string[] $status Status values that need to be considered for filter (required) * @return \Swagger\Client\Model\Pet[] + * @throws \Swagger\Client\ApiException on non-2xx response */ public function findPetsByStatus($status) { @@ -186,15 +203,15 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // query params if($status !== null) { - $queryParams['status'] = $this->apiClient->toQueryValue($status); + $queryParams['status'] = $this->apiClient->getSerializer()->toQueryValue($status); } @@ -208,20 +225,33 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Pet[]'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\Pet[]'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\Pet[]'); return $responseObject; + } /** @@ -231,6 +261,7 @@ class PetApi { * * @param string[] $tags Tags to filter by (required) * @return \Swagger\Client\Model\Pet[] + * @throws \Swagger\Client\ApiException on non-2xx response */ public function findPetsByTags($tags) { @@ -243,15 +274,15 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // query params if($tags !== null) { - $queryParams['tags'] = $this->apiClient->toQueryValue($tags); + $queryParams['tags'] = $this->apiClient->getSerializer()->toQueryValue($tags); } @@ -265,20 +296,33 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Pet[]'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\Pet[]'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\Pet[]'); return $responseObject; + } /** @@ -288,6 +332,7 @@ class PetApi { * * @param int $pet_id ID of pet that needs to be fetched (required) * @return \Swagger\Client\Model\Pet + * @throws \Swagger\Client\ApiException on non-2xx response */ public function getPetById($pet_id) { @@ -305,18 +350,19 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($pet_id !== null) { $resourcePath = str_replace("{" . "petId" . "}", - $this->apiClient->toPathValue($pet_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($pet_id), + $resourcePath); } @@ -328,20 +374,40 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('api_key', 'petstore_auth'); - + + + //TODO support oauth + + $apiKey = $this->apiClient->getApiKeyWithPrefix('api_key'); + if (isset($apiKey)) { + $headerParams['api_key'] = $apiKey; + } + + + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Pet'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\Pet'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\Pet'); return $responseObject; + } /** @@ -353,6 +419,7 @@ class PetApi { * @param string $name Updated name of the pet (required) * @param string $status Updated status of the pet (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function updatePetWithForm($pet_id, $name, $status) { @@ -370,25 +437,26 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/x-www-form-urlencoded')); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array('application/x-www-form-urlencoded')); // path params if($pet_id !== null) { $resourcePath = str_replace("{" . "petId" . "}", - $this->apiClient->toPathValue($pet_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($pet_id), + $resourcePath); } // form params if ($name !== null) { - $formParams['name'] = $this->apiClient->toFormValue($name); + $formParams['name'] = $this->apiClient->getSerializer()->toFormValue($name); }// form params if ($status !== null) { - $formParams['status'] = $this->apiClient->toFormValue($status); + $formParams['status'] = $this->apiClient->getSerializer()->toFormValue($status); } @@ -399,14 +467,21 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -418,6 +493,7 @@ class PetApi { * @param string $api_key (required) * @param int $pet_id Pet id to delete (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function deletePet($api_key, $pet_id) { @@ -435,21 +511,22 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // header params if($api_key !== null) { - $headerParams['api_key'] = $this->apiClient->toHeaderValue($api_key); + $headerParams['api_key'] = $this->apiClient->getSerializer()->toHeaderValue($api_key); } // path params if($pet_id !== null) { $resourcePath = str_replace("{" . "petId" . "}", - $this->apiClient->toPathValue($pet_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($pet_id), + $resourcePath); } @@ -461,14 +538,21 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -481,6 +565,7 @@ class PetApi { * @param string $additional_metadata Additional data to pass to server (required) * @param string $file file to upload (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function uploadFile($pet_id, $additional_metadata, $file) { @@ -498,25 +583,26 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('multipart/form-data')); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array('multipart/form-data')); // path params if($pet_id !== null) { $resourcePath = str_replace("{" . "petId" . "}", - $this->apiClient->toPathValue($pet_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($pet_id), + $resourcePath); } // form params if ($additional_metadata !== null) { - $formParams['additionalMetadata'] = $this->apiClient->toFormValue($additional_metadata); + $formParams['additionalMetadata'] = $this->apiClient->getSerializer()->toFormValue($additional_metadata); }// form params if ($file !== null) { - $formParams['file'] = '@' . $this->apiClient->toFormValue($file); + $formParams['file'] = '@' . $this->apiClient->getSerializer()->toFormValue($file); } @@ -527,16 +613,22 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } - } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Api/StoreApi.php b/samples/client/petstore/php/SwaggerClient-php/lib/Api/StoreApi.php index 07a922aab0a..237ba3f1acf 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Api/StoreApi.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Api/StoreApi.php @@ -22,30 +22,28 @@ namespace Swagger\Client\Api; -use \Swagger\Client\ApiClient; use \Swagger\Client\Configuration; +use \Swagger\Client\ApiClient; +use \Swagger\Client\ApiException; +use \Swagger\Client\ObjectSerializer; class StoreApi { - /** - * @param \Swagger\Client\ApiClient|null $apiClient The api client to use. Defaults to getting it from Configuration - */ - function __construct($apiClient = null) { - if (null === $apiClient) { - if (Configuration::$apiClient === null) { - Configuration::$apiClient = new ApiClient(); // create a new API client if not present - $this->apiClient = Configuration::$apiClient; - } - else - $this->apiClient = Configuration::$apiClient; // use the default one - } else { - $this->apiClient = $apiClient; // use the one provided by the user - } - } - /** @var \Swagger\Client\ApiClient instance of the ApiClient */ private $apiClient; + /** + * @param \Swagger\Client\ApiClient|null $apiClient The api client to use + */ + function __construct($apiClient = null) { + if ($apiClient == null) { + $apiClient = new ApiClient(); + $apiClient->getConfig()->setHost('http://petstore.swagger.io/v2'); + } + + $this->apiClient = $apiClient; + } + /** * @return \Swagger\Client\ApiClient get the API client */ @@ -54,10 +52,12 @@ class StoreApi { } /** - * @param \Swagger\Client $apiClient set the API client + * @param \Swagger\Client\ApiClient $apiClient set the API client + * @return StoreApi */ - public function setApiClient($apiClient) { + public function setApiClient(ApiClient $apiClient) { $this->apiClient = $apiClient; + return $this; } @@ -67,6 +67,7 @@ class StoreApi { * Returns pet inventories by status * * @return map[string,int] + * @throws \Swagger\Client\ApiException on non-2xx response */ public function getInventory() { @@ -79,11 +80,11 @@ class StoreApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -98,20 +99,37 @@ class StoreApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('api_key'); - + + $apiKey = $this->apiClient->getApiKeyWithPrefix('api_key'); + if (isset($apiKey)) { + $headerParams['api_key'] = $apiKey; + } + + + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), 'map[string,int]'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'map[string,int]'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'map[string,int]'); return $responseObject; + } /** @@ -121,6 +139,7 @@ class StoreApi { * * @param \Swagger\Client\Model\Order $body order placed for purchasing the pet (required) * @return \Swagger\Client\Model\Order + * @throws \Swagger\Client\ApiException on non-2xx response */ public function placeOrder($body) { @@ -133,11 +152,11 @@ class StoreApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -156,20 +175,30 @@ class StoreApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Order'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\Order'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\Order'); return $responseObject; + } /** @@ -179,6 +208,7 @@ class StoreApi { * * @param string $order_id ID of pet that needs to be fetched (required) * @return \Swagger\Client\Model\Order + * @throws \Swagger\Client\ApiException on non-2xx response */ public function getOrderById($order_id) { @@ -196,18 +226,19 @@ class StoreApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($order_id !== null) { $resourcePath = str_replace("{" . "orderId" . "}", - $this->apiClient->toPathValue($order_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($order_id), + $resourcePath); } @@ -219,20 +250,30 @@ class StoreApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Order'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\Order'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\Order'); return $responseObject; + } /** @@ -242,6 +283,7 @@ class StoreApi { * * @param string $order_id ID of the order that needs to be deleted (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function deleteOrder($order_id) { @@ -259,18 +301,19 @@ class StoreApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($order_id !== null) { $resourcePath = str_replace("{" . "orderId" . "}", - $this->apiClient->toPathValue($order_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($order_id), + $resourcePath); } @@ -282,16 +325,19 @@ class StoreApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } - } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Api/UserApi.php b/samples/client/petstore/php/SwaggerClient-php/lib/Api/UserApi.php index f4d35a3a7a0..1d0765bbb81 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Api/UserApi.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Api/UserApi.php @@ -22,30 +22,28 @@ namespace Swagger\Client\Api; -use \Swagger\Client\ApiClient; use \Swagger\Client\Configuration; +use \Swagger\Client\ApiClient; +use \Swagger\Client\ApiException; +use \Swagger\Client\ObjectSerializer; class UserApi { - /** - * @param \Swagger\Client\ApiClient|null $apiClient The api client to use. Defaults to getting it from Configuration - */ - function __construct($apiClient = null) { - if (null === $apiClient) { - if (Configuration::$apiClient === null) { - Configuration::$apiClient = new ApiClient(); // create a new API client if not present - $this->apiClient = Configuration::$apiClient; - } - else - $this->apiClient = Configuration::$apiClient; // use the default one - } else { - $this->apiClient = $apiClient; // use the one provided by the user - } - } - /** @var \Swagger\Client\ApiClient instance of the ApiClient */ private $apiClient; + /** + * @param \Swagger\Client\ApiClient|null $apiClient The api client to use + */ + function __construct($apiClient = null) { + if ($apiClient == null) { + $apiClient = new ApiClient(); + $apiClient->getConfig()->setHost('http://petstore.swagger.io/v2'); + } + + $this->apiClient = $apiClient; + } + /** * @return \Swagger\Client\ApiClient get the API client */ @@ -54,10 +52,12 @@ class UserApi { } /** - * @param \Swagger\Client $apiClient set the API client + * @param \Swagger\Client\ApiClient $apiClient set the API client + * @return UserApi */ - public function setApiClient($apiClient) { + public function setApiClient(ApiClient $apiClient) { $this->apiClient = $apiClient; + return $this; } @@ -68,6 +68,7 @@ class UserApi { * * @param \Swagger\Client\Model\User $body Created user object (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function createUser($body) { @@ -80,11 +81,11 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -103,14 +104,18 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -121,6 +126,7 @@ class UserApi { * * @param \Swagger\Client\Model\User[] $body List of user object (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function createUsersWithArrayInput($body) { @@ -133,11 +139,11 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -156,14 +162,18 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -174,6 +184,7 @@ class UserApi { * * @param \Swagger\Client\Model\User[] $body List of user object (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function createUsersWithListInput($body) { @@ -186,11 +197,11 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -209,14 +220,18 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -228,6 +243,7 @@ class UserApi { * @param string $username The user name for login (required) * @param string $password The password for login in clear text (required) * @return string + * @throws \Swagger\Client\ApiException on non-2xx response */ public function loginUser($username, $password) { @@ -240,18 +256,18 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // query params if($username !== null) { - $queryParams['username'] = $this->apiClient->toQueryValue($username); + $queryParams['username'] = $this->apiClient->getSerializer()->toQueryValue($username); }// query params if($password !== null) { - $queryParams['password'] = $this->apiClient->toQueryValue($password); + $queryParams['password'] = $this->apiClient->getSerializer()->toQueryValue($password); } @@ -265,20 +281,30 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), 'string'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'string'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'string'); return $responseObject; + } /** @@ -287,6 +313,7 @@ class UserApi { * Logs out current logged in user session * * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function logoutUser() { @@ -299,11 +326,11 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -318,14 +345,18 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -336,6 +367,7 @@ class UserApi { * * @param string $username The name that needs to be fetched. Use user1 for testing. (required) * @return \Swagger\Client\Model\User + * @throws \Swagger\Client\ApiException on non-2xx response */ public function getUserByName($username) { @@ -353,18 +385,19 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($username !== null) { $resourcePath = str_replace("{" . "username" . "}", - $this->apiClient->toPathValue($username), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($username), + $resourcePath); } @@ -376,20 +409,30 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\User'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\User'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\User'); return $responseObject; + } /** @@ -400,6 +443,7 @@ class UserApi { * @param string $username name that need to be deleted (required) * @param \Swagger\Client\Model\User $body Updated user object (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function updateUser($username, $body) { @@ -417,18 +461,19 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($username !== null) { $resourcePath = str_replace("{" . "username" . "}", - $this->apiClient->toPathValue($username), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($username), + $resourcePath); } // body params @@ -444,14 +489,18 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -462,6 +511,7 @@ class UserApi { * * @param string $username The name that needs to be deleted (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function deleteUser($username) { @@ -479,18 +529,19 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($username !== null) { $resourcePath = str_replace("{" . "username" . "}", - $this->apiClient->toPathValue($username), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($username), + $resourcePath); } @@ -502,16 +553,19 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } - } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/ApiClient.php b/samples/client/petstore/php/SwaggerClient-php/lib/ApiClient.php index bb5229fb170..66204f0c4f3 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/ApiClient.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/ApiClient.php @@ -25,146 +25,60 @@ class ApiClient { public static $PUT = "PUT"; public static $DELETE = "DELETE"; - /** @var string[] Array of default headers where the key is the header name and the value is the header value */ - private $default_header = array(); + /** @var Configuration */ + protected $config; - /** @var string timeout (second) of the HTTP request, by default set to 0, no timeout */ - protected $curl_timeout = 0; - - /** @var string user agent of the HTTP request, set to "PHP-Swagger" by default */ - protected $user_agent = "PHP-Swagger"; + /** @var ObjectSerializer */ + protected $serializer; /** - * @param string $host Base url of the API server (optional) + * @param Configuration $config config for this ApiClient */ - function __construct($host = null) { - if ($host === null) { - $this->host = 'http://petstore.swagger.io/v2'; - } else { - $this->host = $host; + function __construct(Configuration $config = null) { + if ($config == null) { + $config = Configuration::getDefaultConfiguration(); } + + $this->config = $config; + $this->serializer = new ObjectSerializer(); } /** - * add default header - * - * @param string $header_name header name (e.g. Token) - * @param string $header_value header value (e.g. 1z8wp3) + * get the config + * @return Configuration */ - public function addDefaultHeader($header_name, $header_value) { - if (!is_string($header_name)) - throw new \InvalidArgumentException('Header name must be a string.'); - - $this->default_header[$header_name] = $header_value; + public function getConfig() { + return $this->config; } /** - * get the default header - * - * @return array default header + * get the serializer + * @return ObjectSerializer */ - public function getDefaultHeader() { - return $this->default_header; + public function getSerializer() { + return $this->serializer; } - /** - * delete the default header based on header name - * - * @param string $header_name header name (e.g. Token) - */ - public function deleteDefaultHeader($header_name) { - unset($this->default_header[$header_name]); - } - - /** - * set the user agent of the api client - * - * @param string $user_agent the user agent of the api client - */ - public function setUserAgent($user_agent) { - if (!is_string($user_agent)) - throw new \InvalidArgumentException('User-agent must be a string.'); - - $this->user_agent= $user_agent; - } - - /** - * get the user agent of the api client - * - * @return string user agent - */ - public function getUserAgent($user_agent) { - return $this->user_agent; - } - - /** - * set the HTTP timeout value - * - * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] - */ - public function setTimeout($seconds) { - if (!is_numeric($seconds) || $seconds < 0) - throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); - - $this->curl_timeout = $seconds; - } - - /** - * get the HTTP timeout value - * - * @return string HTTP timeout value - */ - public function getTimeout() { - return $this->curl_timeout; - } - - /** * Get API key (with prefix if set) - * @param string key name + * @param string $apiKey name of apikey * @return string API key with the prefix */ public function getApiKeyWithPrefix($apiKey) { - if (isset(Configuration::$apiKeyPrefix[$apiKey])) { - return Configuration::$apiKeyPrefix[$apiKey]." ".Configuration::$apiKey[$apiKey]; - } else if (isset(Configuration::$apiKey[$apiKey])) { - return Configuration::$apiKey[$apiKey]; + $prefix = $this->config->getApiKeyPrefix($apiKey); + $apiKey = $this->config->getApiKey($apiKey); + + if (!isset($apiKey)) { + return null; + } + + if (isset($prefix)) { + $keyWithPrefix = $prefix." ".$apiKey; } else { - return; + $keyWithPrefix = $apiKey; } - } - /** - * update hearder and query param based on authentication setting - * - * @param array $headerParams header parameters (by ref) - * @param array $queryParams query parameters (by ref) - * @param array $authSettings array of authentication scheme (e.g ['api_key']) - */ - public function updateParamsForAuth(&$headerParams, &$queryParams, $authSettings) - { - if (count($authSettings) == 0) - return; - - // one endpoint can have more than 1 auth settings - foreach($authSettings as $auth) { - // determine which one to use - switch($auth) { - - case 'api_key': - $headerParams['api_key'] = $this->getApiKeyWithPrefix('api_key'); - - break; - - case 'petstore_auth': - - //TODO support oauth - break; - - default: - //TODO show warning about security definition not found - } - } + return $keyWithPrefix; } /** @@ -173,18 +87,15 @@ class ApiClient { * @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 + * @throws \Swagger\Client\ApiException on a non 2xx response * @return mixed */ - public function callApi($resourcePath, $method, $queryParams, $postData, - $headerParams, $authSettings) { + public function callApi($resourcePath, $method, $queryParams, $postData, $headerParams) { $headers = array(); - # determine authentication setting - $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); - # construct the http header - $headerParams = array_merge((array)$this->default_header, (array)$headerParams); + $headerParams = array_merge((array)$this->config->getDefaultHeaders(), (array)$headerParams); foreach ($headerParams as $key => $val) { $headers[] = "$key: $val"; @@ -195,15 +106,15 @@ class ApiClient { $postData = http_build_query($postData); } else if ((is_object($postData) or is_array($postData)) and !in_array('Content-Type: multipart/form-data', $headers)) { // json model - $postData = json_encode($this->sanitizeForSerialization($postData)); + $postData = json_encode($this->serializer->sanitizeForSerialization($postData)); } - $url = $this->host . $resourcePath; + $url = $this->config->getHost() . $resourcePath; $curl = curl_init(); // set timeout, if needed - if ($this->curl_timeout != 0) { - curl_setopt($curl, CURLOPT_TIMEOUT, $this->curl_timeout); + if ($this->config->getCurlTimeout() != 0) { + curl_setopt($curl, CURLOPT_TIMEOUT, $this->config->getCurlTimeout()); } // return the result on success, rather than just TRUE curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); @@ -232,14 +143,14 @@ class ApiClient { curl_setopt($curl, CURLOPT_URL, $url); // Set user agent - curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent); + curl_setopt($curl, CURLOPT_USERAGENT, $this->config->getUserAgent()); // debugging for curl - if (Configuration::$debug) { - error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, Configuration::$debug_file); + if ($this->config->getDebug()) { + error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, $this->config->getDebugFile()); curl_setopt($curl, CURLOPT_VERBOSE, 1); - curl_setopt($curl, CURLOPT_STDERR, fopen(Configuration::$debug_file, 'a')); + curl_setopt($curl, CURLOPT_STDERR, fopen($this->config->getDebugFile(), 'a')); } else { curl_setopt($curl, CURLOPT_VERBOSE, 0); } @@ -255,8 +166,8 @@ class ApiClient { $response_info = curl_getinfo($curl); // debug HTTP response body - if (Configuration::$debug) { - error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, Configuration::$debug_file); + if ($this->config->getDebug()) { + error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, $this->config->getDebugFile()); } // Handle the response @@ -274,153 +185,13 @@ class ApiClient { 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) { - if ($data->$property !== null) { - $values[$data::$attributeMap[$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 function toPathValue($value) { - return rawurlencode($this->toString($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 function toQueryValue($object) { - if (is_array($object)) { - return implode(',', $object); - } else { - return $this->toString($object); - } - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the header. If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value a string which will be part of the header - * @return string the header string - */ - public function toHeaderValue($value) { - return $this->toString($value); - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the http body (form parameter). If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value the value of the form parameter - * @return string the form string - */ - public function toFormValue($value) { - return $this->toString($value); - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the parameter. If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value the value of the parameter - * @return string the header string - */ - public function toString($value) { - if ($value instanceof \DateTime) { // datetime in ISO8601 format - return $value->format(\DateTime::ISO8601); - } - else { - 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 function deserialize($data, $class) - { - if (null === $data) { - $deserialized = null; - } elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] - $inner = substr($class, 4, -1); - $deserialized = array(); - if(strrpos($inner, ",") !== false) { - $subClass_array = explode(',', $inner, 2); - $subClass = $subClass_array[1]; - foreach ($data as $key => $value) { - $deserialized[$key] = $this->deserialize($value, $subClass); - } - } - } elseif (strcasecmp(substr($class, -2),'[]') == 0) { - $subClass = substr($class, 0, -2); - $values = array(); - foreach ($data as $key => $value) { - $values[] = $this->deserialize($value, $subClass); - } - $deserialized = $values; - } elseif ($class == 'DateTime') { - $deserialized = new \DateTime($data); - } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { - settype($data, $class); - $deserialized = $data; - } else { - $instance = new $class(); - foreach ($instance::$swaggerTypes as $property => $type) { - $original_property_name = $instance::$attributeMap[$property]; - if (isset($original_property_name) && isset($data->$original_property_name)) { - $instance->$property = $this->deserialize($data->$original_property_name, $type); - } - } - $deserialized = $instance; - } - - return $deserialized; - } - /* * return the header 'Accept' based on an array of Accept provided * - * @param array[string] $accept Array of header + * @param string[] $accept Array of header * @return string Accept (e.g. application/json) */ - public function selectHeaderAccept($accept) { + public static function selectHeaderAccept($accept) { if (count($accept) === 0 or (count($accept) === 1 and $accept[0] === '')) { return NULL; } elseif (preg_grep("/application\/json/i", $accept)) { @@ -433,10 +204,10 @@ class ApiClient { /* * return the content type based on an array of content-type provided * - * @param array[string] content_type_array Array fo content-type + * @param string[] content_type_array Array fo content-type * @return string Content-Type (e.g. application/json) */ - public function selectHeaderContentType($content_type) { + public static function selectHeaderContentType($content_type) { if (count($content_type) === 0 or (count($content_type) === 1 and $content_type[0] === '')) { return 'application/json'; } elseif (preg_grep("/application\/json/i", $content_type)) { @@ -445,6 +216,4 @@ class ApiClient { return implode(',', $content_type); } } - } - diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php b/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php index 5f3b1812261..51774137aed 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php @@ -22,15 +22,20 @@ use \Exception; class ApiException extends Exception { /** @var string The HTTP body of the server response. */ - protected $response_body; + protected $responseBody; /** @var string[] The HTTP header of the server response. */ - protected $response_headers; + protected $responseHeaders; + + /** + * The deserialized response object + */ + protected $responseObject; public function __construct($message="", $code=0, $responseHeaders=null, $responseBody=null) { parent::__construct($message, $code); - $this->response_headers = $responseHeaders; - $this->response_body = $responseBody; + $this->responseHeaders = $responseHeaders; + $this->responseBody = $responseBody; } /** @@ -39,7 +44,7 @@ class ApiException extends Exception { * @return string HTTP response header */ public function getResponseHeaders() { - return $this->response_headers; + return $this->responseHeaders; } /** @@ -48,7 +53,18 @@ class ApiException extends Exception { * @return string HTTP response body */ public function getResponseBody() { - return $this->response_body; + return $this->responseBody; } + /** + * sets the deseralized response object (during deserialization) + * @param mixed $obj + */ + public function setResponseObject($obj) { + $this->responseObject = $obj; + } + + public function getResponseObject() { + return $this->responseObject; + } } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php index e6381781bb0..a407fe4dd49 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php @@ -17,37 +17,250 @@ namespace Swagger\Client; -use \Swagger\Client\ApiClient; - class Configuration { + private static $defaultConfiguration = null; + /** @var string[] Associate array to store API key(s) */ - public static $apiKey = array(); + protected $apiKeys = array(); /** string[] Associate array to store API prefix (e.g. Bearer) */ - public static $apiKeyPrefix = array(); + protected $apiKeyPrefixes = array(); /** @var string Username for HTTP basic authentication */ - public static $username = ''; + protected $username = ''; /** @var string Password for HTTP basic authentication */ - public static $password = ''; + protected $password = ''; /** @var \Swagger\Client\ApiClient The default instance of ApiClient */ - public static $apiClient; + protected $defaultHeaders = array(); + + /** @var string The host */ + protected $host = 'http://localhost'; + + /** @var string timeout (second) of the HTTP request, by default set to 0, no timeout */ + protected $curlTimeout = 0; + + /** @var string user agent of the HTTP request, set to "PHP-Swagger" by default */ + protected $userAgent = "PHP-Swagger"; /** @var bool Debug switch (default set to false) */ - public static $debug = false; + protected $debug = false; /** @var string Debug file location (log to STDOUT by default) */ - public static $debug_file = 'php://output'; + protected $debugFile = 'php://output'; - /* - * manually initalize ApiClient + /** + * @param string $key + * @param string $value + * @return Configuration */ - public static function init() { - if (self::$apiClient === null) - self::$apiClient = new ApiClient(); + public function setApiKey($key, $value) { + $this->apiKeys[$key] = $value; + return $this; } + /** + * @param $key + * @return string + */ + public function getApiKey($key) { + return isset($this->apiKeys[$key]) ? $this->apiKeys[$key] : null; + } + + /** + * @param string $key + * @param string $value + * @return Configuration + */ + public function setApiKeyPrefix($key, $value) { + $this->apiKeyPrefixes[$key] = $value; + return $this; + } + + /** + * @param $key + * @return string + */ + public function getApiKeyPrefix($key) { + return isset($this->apiKeyPrefixes[$key]) ? $this->apiKeyPrefixes[$key] : null; + } + + /** + * @param string $username + * @return Configuration + */ + public function setUsername($username) { + $this->username = $username; + return $this; + } + + /** + * @return string + */ + public function getUsername() { + return $this->username; + } + + /** + * @param string $password + * @return Configuration + */ + public function setPassword($password) { + $this->password = $password; + return $this; + } + + /** + * @return string + */ + public function getPassword() { + return $this->password; + } + + /** + * add default header + * + * @param string $headerName header name (e.g. Token) + * @param string $headerValue header value (e.g. 1z8wp3) + * @return ApiClient + */ + public function addDefaultHeader($headerName, $headerValue) { + if (!is_string($headerName)) { + throw new \InvalidArgumentException('Header name must be a string.'); + } + + $this->defaultHeaders[$headerName] = $headerValue; + return $this; + } + + /** + * get the default header + * + * @return array default header + */ + public function getDefaultHeaders() { + return $this->defaultHeaders; + } + + /** + * delete a default header + * @param string $headerName the header to delete + * @return Configuration + */ + public function deleteDefaultHeader($headerName) { + unset($this->defaultHeaders[$headerName]); + } + + /** + * @param string $host + * @return Configuration + */ + public function setHost($host) { + $this->host = $host; + return $this; + } + + /** + * @return string + */ + public function getHost() { + return $this->host; + } + + /** + * set the user agent of the api client + * + * @param string $userAgent the user agent of the api client + * @return ApiClient + */ + public function setUserAgent($userAgent) { + if (!is_string($userAgent)) { + throw new \InvalidArgumentException('User-agent must be a string.'); + } + + $this->userAgent = $userAgent; + return $this; + } + + /** + * get the user agent of the api client + * + * @return string user agent + */ + public function getUserAgent() { + return $this->userAgent; + } + + /** + * set the HTTP timeout value + * + * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] + * @return ApiClient + */ + public function setCurlTimeout($seconds) { + if (!is_numeric($seconds) || $seconds < 0) { + throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); + } + + $this->curlTimeout = $seconds; + return $this; + } + + /** + * get the HTTP timeout value + * + * @return string HTTP timeout value + */ + public function getCurlTimeout() { + return $this->curlTimeout; + } + + /** + * @param bool $debug + * @return Configuration + */ + public function setDebug($debug) { + $this->debug = $debug; + return $this; + } + + /** + * @return bool + */ + public function getDebug() { + return $this->debug; + } + + /** + * @param string $debugFile + * @return Configuration + */ + public function setDebugFile($debugFile) { + $this->debugFile = $debugFile; + return $this; + } + + /** + * @return string + */ + public function getDebugFile() { + return $this->debugFile; + } + + /** + * @return Configuration + */ + public static function getDefaultConfiguration() { + if (self::$defaultConfiguration == null) { + return new Configuration(); + } + + return self::$defaultConfiguration; + } + + public static function setDefaultConfiguration(Configuration $config) { + self::$defaultConfiguration = $config; + } } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Category.php b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Category.php index 750a8fee5df..75aaf2eeead 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Category.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Category.php @@ -38,21 +38,69 @@ class Category implements ArrayAccess { 'id' => 'id', 'name' => 'name' ); + + /** @var string[] Array of attributes to setter functions (for deserialization of responses) */ + static $setters = array( + 'id' => 'setId', + 'name' => 'setName' + ); + + /** @var string[] Array of attributes to getter functions (for serialization of requests) */ + static $getters = array( + 'id' => 'getId', + 'name' => 'getName' + ); + /** @var int $id */ - public $id; + protected $id; /** @var string $name */ - public $name; + protected $name; + + public function __construct(array $data = null) { + if ($data != null) { + $this->id = $data["id"]; + $this->name = $data["name"]; + } + } /** - * @param mixed[] Array of parameters to initialize the object with + * get id + * @return int */ - public function __construct(array $data = null) { - $this->id = @$data["id"]; - $this->name = @$data["name"]; + public function getId() { + return $this->id; } + /** + * set id + * @param int $id + * @return $this + */ + public function setId($id) { + $this->id = $id; + return $this; + } + + /** + * get name + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * set name + * @param string $name + * @return $this + */ + public function setName($name) { + $this->name = $name; + return $this; + } + public function offsetExists($offset) { return isset($this->$offset); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Order.php b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Order.php index 64552afb763..c7a433c3d8c 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Order.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Order.php @@ -46,37 +46,165 @@ class Order implements ArrayAccess { 'status' => 'status', 'complete' => 'complete' ); + + /** @var string[] Array of attributes to setter functions (for deserialization of responses) */ + static $setters = array( + 'id' => 'setId', + 'pet_id' => 'setPetId', + 'quantity' => 'setQuantity', + 'ship_date' => 'setShipDate', + 'status' => 'setStatus', + 'complete' => 'setComplete' + ); + + /** @var string[] Array of attributes to getter functions (for serialization of requests) */ + static $getters = array( + 'id' => 'getId', + 'pet_id' => 'getPetId', + 'quantity' => 'getQuantity', + 'ship_date' => 'getShipDate', + 'status' => 'getStatus', + 'complete' => 'getComplete' + ); + /** @var int $id */ - public $id; + protected $id; /** @var int $pet_id */ - public $pet_id; + protected $pet_id; /** @var int $quantity */ - public $quantity; + protected $quantity; /** @var \DateTime $ship_date */ - public $ship_date; + protected $ship_date; /** @var string $status Order Status */ - public $status; + protected $status; /** @var bool $complete */ - public $complete; + protected $complete; + + public function __construct(array $data = null) { + if ($data != null) { + $this->id = $data["id"]; + $this->pet_id = $data["pet_id"]; + $this->quantity = $data["quantity"]; + $this->ship_date = $data["ship_date"]; + $this->status = $data["status"]; + $this->complete = $data["complete"]; + } + } /** - * @param mixed[] Array of parameters to initialize the object with + * get id + * @return int */ - public function __construct(array $data = null) { - $this->id = @$data["id"]; - $this->pet_id = @$data["pet_id"]; - $this->quantity = @$data["quantity"]; - $this->ship_date = @$data["ship_date"]; - $this->status = @$data["status"]; - $this->complete = @$data["complete"]; + public function getId() { + return $this->id; } + /** + * set id + * @param int $id + * @return $this + */ + public function setId($id) { + $this->id = $id; + return $this; + } + + /** + * get pet_id + * @return int + */ + public function getPetId() { + return $this->pet_id; + } + + /** + * set pet_id + * @param int $pet_id + * @return $this + */ + public function setPetId($pet_id) { + $this->pet_id = $pet_id; + return $this; + } + + /** + * get quantity + * @return int + */ + public function getQuantity() { + return $this->quantity; + } + + /** + * set quantity + * @param int $quantity + * @return $this + */ + public function setQuantity($quantity) { + $this->quantity = $quantity; + return $this; + } + + /** + * get ship_date + * @return \DateTime + */ + public function getShipDate() { + return $this->ship_date; + } + + /** + * set ship_date + * @param \DateTime $ship_date + * @return $this + */ + public function setShipDate($ship_date) { + $this->ship_date = $ship_date; + return $this; + } + + /** + * get status + * @return string + */ + public function getStatus() { + return $this->status; + } + + /** + * set status + * @param string $status + * @return $this + */ + public function setStatus($status) { + $this->status = $status; + return $this; + } + + /** + * get complete + * @return bool + */ + public function getComplete() { + return $this->complete; + } + + /** + * set complete + * @param bool $complete + * @return $this + */ + public function setComplete($complete) { + $this->complete = $complete; + return $this; + } + public function offsetExists($offset) { return isset($this->$offset); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Pet.php b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Pet.php index ef2a4c76a0d..cbe27e1fce9 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Pet.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Pet.php @@ -46,37 +46,165 @@ class Pet implements ArrayAccess { 'tags' => 'tags', 'status' => 'status' ); + + /** @var string[] Array of attributes to setter functions (for deserialization of responses) */ + static $setters = array( + 'id' => 'setId', + 'category' => 'setCategory', + 'name' => 'setName', + 'photo_urls' => 'setPhotoUrls', + 'tags' => 'setTags', + 'status' => 'setStatus' + ); + + /** @var string[] Array of attributes to getter functions (for serialization of requests) */ + static $getters = array( + 'id' => 'getId', + 'category' => 'getCategory', + 'name' => 'getName', + 'photo_urls' => 'getPhotoUrls', + 'tags' => 'getTags', + 'status' => 'getStatus' + ); + /** @var int $id */ - public $id; + protected $id; /** @var \Swagger\Client\Model\Category $category */ - public $category; + protected $category; /** @var string $name */ - public $name; + protected $name; /** @var string[] $photo_urls */ - public $photo_urls; + protected $photo_urls; /** @var \Swagger\Client\Model\Tag[] $tags */ - public $tags; + protected $tags; /** @var string $status pet status in the store */ - public $status; + protected $status; + + public function __construct(array $data = null) { + if ($data != null) { + $this->id = $data["id"]; + $this->category = $data["category"]; + $this->name = $data["name"]; + $this->photo_urls = $data["photo_urls"]; + $this->tags = $data["tags"]; + $this->status = $data["status"]; + } + } /** - * @param mixed[] Array of parameters to initialize the object with + * get id + * @return int */ - public function __construct(array $data = null) { - $this->id = @$data["id"]; - $this->category = @$data["category"]; - $this->name = @$data["name"]; - $this->photo_urls = @$data["photo_urls"]; - $this->tags = @$data["tags"]; - $this->status = @$data["status"]; + public function getId() { + return $this->id; } + /** + * set id + * @param int $id + * @return $this + */ + public function setId($id) { + $this->id = $id; + return $this; + } + + /** + * get category + * @return \Swagger\Client\Model\Category + */ + public function getCategory() { + return $this->category; + } + + /** + * set category + * @param \Swagger\Client\Model\Category $category + * @return $this + */ + public function setCategory($category) { + $this->category = $category; + return $this; + } + + /** + * get name + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * set name + * @param string $name + * @return $this + */ + public function setName($name) { + $this->name = $name; + return $this; + } + + /** + * get photo_urls + * @return string[] + */ + public function getPhotoUrls() { + return $this->photo_urls; + } + + /** + * set photo_urls + * @param string[] $photo_urls + * @return $this + */ + public function setPhotoUrls($photo_urls) { + $this->photo_urls = $photo_urls; + return $this; + } + + /** + * get tags + * @return \Swagger\Client\Model\Tag[] + */ + public function getTags() { + return $this->tags; + } + + /** + * set tags + * @param \Swagger\Client\Model\Tag[] $tags + * @return $this + */ + public function setTags($tags) { + $this->tags = $tags; + return $this; + } + + /** + * get status + * @return string + */ + public function getStatus() { + return $this->status; + } + + /** + * set status + * @param string $status + * @return $this + */ + public function setStatus($status) { + $this->status = $status; + return $this; + } + public function offsetExists($offset) { return isset($this->$offset); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Tag.php b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Tag.php index 5959cb20a6a..3fd785f001b 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Tag.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Tag.php @@ -38,21 +38,69 @@ class Tag implements ArrayAccess { 'id' => 'id', 'name' => 'name' ); + + /** @var string[] Array of attributes to setter functions (for deserialization of responses) */ + static $setters = array( + 'id' => 'setId', + 'name' => 'setName' + ); + + /** @var string[] Array of attributes to getter functions (for serialization of requests) */ + static $getters = array( + 'id' => 'getId', + 'name' => 'getName' + ); + /** @var int $id */ - public $id; + protected $id; /** @var string $name */ - public $name; + protected $name; + + public function __construct(array $data = null) { + if ($data != null) { + $this->id = $data["id"]; + $this->name = $data["name"]; + } + } /** - * @param mixed[] Array of parameters to initialize the object with + * get id + * @return int */ - public function __construct(array $data = null) { - $this->id = @$data["id"]; - $this->name = @$data["name"]; + public function getId() { + return $this->id; } + /** + * set id + * @param int $id + * @return $this + */ + public function setId($id) { + $this->id = $id; + return $this; + } + + /** + * get name + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * set name + * @param string $name + * @return $this + */ + public function setName($name) { + $this->name = $name; + return $this; + } + public function offsetExists($offset) { return isset($this->$offset); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Model/User.php b/samples/client/petstore/php/SwaggerClient-php/lib/Model/User.php index 1bfb7f332db..2bb31056bde 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Model/User.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Model/User.php @@ -50,45 +50,213 @@ class User implements ArrayAccess { 'phone' => 'phone', 'user_status' => 'userStatus' ); + + /** @var string[] Array of attributes to setter functions (for deserialization of responses) */ + static $setters = array( + 'id' => 'setId', + 'username' => 'setUsername', + 'first_name' => 'setFirstName', + 'last_name' => 'setLastName', + 'email' => 'setEmail', + 'password' => 'setPassword', + 'phone' => 'setPhone', + 'user_status' => 'setUserStatus' + ); + + /** @var string[] Array of attributes to getter functions (for serialization of requests) */ + static $getters = array( + 'id' => 'getId', + 'username' => 'getUsername', + 'first_name' => 'getFirstName', + 'last_name' => 'getLastName', + 'email' => 'getEmail', + 'password' => 'getPassword', + 'phone' => 'getPhone', + 'user_status' => 'getUserStatus' + ); + /** @var int $id */ - public $id; + protected $id; /** @var string $username */ - public $username; + protected $username; /** @var string $first_name */ - public $first_name; + protected $first_name; /** @var string $last_name */ - public $last_name; + protected $last_name; /** @var string $email */ - public $email; + protected $email; /** @var string $password */ - public $password; + protected $password; /** @var string $phone */ - public $phone; + protected $phone; /** @var int $user_status User Status */ - public $user_status; + protected $user_status; + + public function __construct(array $data = null) { + if ($data != null) { + $this->id = $data["id"]; + $this->username = $data["username"]; + $this->first_name = $data["first_name"]; + $this->last_name = $data["last_name"]; + $this->email = $data["email"]; + $this->password = $data["password"]; + $this->phone = $data["phone"]; + $this->user_status = $data["user_status"]; + } + } /** - * @param mixed[] Array of parameters to initialize the object with + * get id + * @return int */ - public function __construct(array $data = null) { - $this->id = @$data["id"]; - $this->username = @$data["username"]; - $this->first_name = @$data["first_name"]; - $this->last_name = @$data["last_name"]; - $this->email = @$data["email"]; - $this->password = @$data["password"]; - $this->phone = @$data["phone"]; - $this->user_status = @$data["user_status"]; + public function getId() { + return $this->id; } + /** + * set id + * @param int $id + * @return $this + */ + public function setId($id) { + $this->id = $id; + return $this; + } + + /** + * get username + * @return string + */ + public function getUsername() { + return $this->username; + } + + /** + * set username + * @param string $username + * @return $this + */ + public function setUsername($username) { + $this->username = $username; + return $this; + } + + /** + * get first_name + * @return string + */ + public function getFirstName() { + return $this->first_name; + } + + /** + * set first_name + * @param string $first_name + * @return $this + */ + public function setFirstName($first_name) { + $this->first_name = $first_name; + return $this; + } + + /** + * get last_name + * @return string + */ + public function getLastName() { + return $this->last_name; + } + + /** + * set last_name + * @param string $last_name + * @return $this + */ + public function setLastName($last_name) { + $this->last_name = $last_name; + return $this; + } + + /** + * get email + * @return string + */ + public function getEmail() { + return $this->email; + } + + /** + * set email + * @param string $email + * @return $this + */ + public function setEmail($email) { + $this->email = $email; + return $this; + } + + /** + * get password + * @return string + */ + public function getPassword() { + return $this->password; + } + + /** + * set password + * @param string $password + * @return $this + */ + public function setPassword($password) { + $this->password = $password; + return $this; + } + + /** + * get phone + * @return string + */ + public function getPhone() { + return $this->phone; + } + + /** + * set phone + * @param string $phone + * @return $this + */ + public function setPhone($phone) { + $this->phone = $phone; + return $this; + } + + /** + * get user_status + * @return int + */ + public function getUserStatus() { + return $this->user_status; + } + + /** + * set user_status + * @param int $user_status + * @return $this + */ + public function setUserStatus($user_status) { + $this->user_status = $user_status; + return $this; + } + public function offsetExists($offset) { return isset($this->$offset); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/ObjectSerializer.php b/samples/client/petstore/php/SwaggerClient-php/lib/ObjectSerializer.php new file mode 100644 index 00000000000..802a49bc01a --- /dev/null +++ b/samples/client/petstore/php/SwaggerClient-php/lib/ObjectSerializer.php @@ -0,0 +1,151 @@ +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) { + $getter = $data::$getters[$property]; + if ($data->$getter() !== null) { + $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$getter()); + } + } + $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 function toPathValue($value) { + return rawurlencode($this->toString($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 function toQueryValue($object) { + if (is_array($object)) { + return implode(',', $object); + } else { + return $this->toString($object); + } + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the header. If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value a string which will be part of the header + * @return string the header string + */ + public function toHeaderValue($value) { + return $this->toString($value); + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the http body (form parameter). If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value the value of the form parameter + * @return string the form string + */ + public function toFormValue($value) { + return $this->toString($value); + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the parameter. If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value the value of the parameter + * @return string the header string + */ + public function toString($value) { + if ($value instanceof \DateTime) { // datetime in ISO8601 format + return $value->format(\DateTime::ISO8601); + } else { + return $value; + } + } + + /** + * Deserialize a JSON string into an object + * + * @param mixed $data object or primitive to be deserialized + * @param string $class class name is passed as a string + * @return object an instance of $class + */ + public function deserialize($data, $class) { + if (null === $data) { + $deserialized = null; + } elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] + $inner = substr($class, 4, -1); + $deserialized = array(); + if(strrpos($inner, ",") !== false) { + $subClass_array = explode(',', $inner, 2); + $subClass = $subClass_array[1]; + foreach ($data as $key => $value) { + $deserialized[$key] = $this->deserialize($value, $subClass); + } + } + } elseif (strcasecmp(substr($class, -2),'[]') == 0) { + $subClass = substr($class, 0, -2); + $values = array(); + foreach ($data as $key => $value) { + $values[] = $this->deserialize($value, $subClass); + } + $deserialized = $values; + } elseif ($class == 'DateTime') { + $deserialized = new \DateTime($data); + } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { + settype($data, $class); + $deserialized = $data; + } else { + $instance = new $class(); + foreach ($instance::$swaggerTypes as $property => $type) { + $propertySetter = $instance::$setters[$property]; + + if (!isset($propertySetter) || !isset($data->{$instance::$attributeMap[$property]})) { + continue; + } + + $propertyValue = $data->{$instance::$attributeMap[$property]}; + if (isset($propertyValue)) { + $instance->$propertySetter($this->deserialize($propertyValue, $type)); + } + } + $deserialized = $instance; + } + + return $deserialized; + } +} \ No newline at end of file diff --git a/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php b/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php index 131a79dba92..3ac28772291 100644 --- a/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php +++ b/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php @@ -22,19 +22,19 @@ class PetApiTest extends \PHPUnit_Framework_TestCase // new pet $new_pet_id = 10005; $new_pet = new Swagger\Client\Model\Pet; - $new_pet->id = $new_pet_id; - $new_pet->name = "PHP Unit Test"; + $new_pet->setId($new_pet_id); + $new_pet->setName("PHP Unit Test"); // new tag $tag= new Swagger\Client\Model\Tag; - $tag->id = $new_pet_id; // use the same id as pet - $tag->name = "test php tag"; + $tag->setId($new_pet_id); // use the same id as pet + $tag->setName("test php tag"); // new category $category = new Swagger\Client\Model\Category; - $category->id = $new_pet_id; // use the same id as pet - $category->name = "test php category"; + $category->setId($new_pet_id); // use the same id as pet + $category->setName("test php category"); - $new_pet->tags = array($tag); - $new_pet->category = $category; + $new_pet->setTags(array($tag)); + $new_pet->setCategory($category); $pet_api = new Swagger\Client\Api\PetAPI(); // add a new pet (model) @@ -56,65 +56,53 @@ class PetApiTest extends \PHPUnit_Framework_TestCase $this->assertSame('application/yaml,application/xml', $api_client->selectHeaderContentType(array('application/yaml','application/xml'))); // test addDefaultHeader and getDefaultHeader - $api_client->addDefaultHeader('test1', 'value1'); - $api_client->addDefaultHeader('test2', 200); - $defaultHeader = $api_client->getDefaultHeader(); + $api_client->getConfig()->addDefaultHeader('test1', 'value1'); + $api_client->getConfig()->addDefaultHeader('test2', 200); + $defaultHeader = $api_client->getConfig()->getDefaultHeaders(); $this->assertSame('value1', $defaultHeader['test1']); $this->assertSame(200, $defaultHeader['test2']); // test deleteDefaultHeader - $api_client->deleteDefaultHeader('test2'); - $defaultHeader = $api_client->getDefaultHeader(); + $api_client->getConfig()->deleteDefaultHeader('test2'); + $defaultHeader = $api_client->getConfig()->getDefaultHeaders(); $this->assertFalse(isset($defaultHeader['test2'])); - $pet_api = new Swagger\Client\Api\PetAPI(); $pet_api2 = new Swagger\Client\Api\PetAPI(); $apiClient3 = new Swagger\Client\ApiClient(); - $apiClient3->setUserAgent = 'api client 3'; + $apiClient3->getConfig()->setUserAgent('api client 3'); $apiClient4 = new Swagger\Client\ApiClient(); - $apiClient4->setUserAgent = 'api client 4'; + $apiClient4->getConfig()->setUserAgent('api client 4'); $pet_api3 = new Swagger\Client\Api\PetAPI($apiClient3); - // same default api client - $this->assertSame($pet_api->getApiClient(), $pet_api2->getApiClient()); - // confirm using the default api client in the Configuration - $this->assertSame($pet_api->getApiClient(), Swagger\Client\Configuration::$apiClient); // 2 different api clients are not the same $this->assertNotEquals($apiClient3, $apiClient4); - // customized pet api not using the default (configuration) api client - $this->assertNotEquals($pet_api3->getApiClient(), Swagger\Client\Configuration::$apiClient); // customied pet api not using the old pet api's api client $this->assertNotEquals($pet_api2->getApiClient(), $pet_api3->getApiClient()); - - // both pet api and pet api2 share the same api client and confirm using timeout value - $pet_api->getApiClient()->setTimeout(999); - $this->assertSame(999, $pet_api2->getApiClient()->getTimeout()); - } // test getPetById with a Pet object (id 10005) public function testGetPetById() { // initialize the API client without host - $api_client = new Swagger\Client\ApiClient(); - Swagger\Client\Configuration::$apiKey['api_key'] = '111222333444555'; $pet_id = 10005; // ID of pet that needs to be fetched - $pet_api = new Swagger\Client\Api\PetAPI($api_client); + $pet_api = new Swagger\Client\Api\PetAPI(); + $pet_api->getApiClient()->getConfig()->setApiKey('api_key', '111222333444555'); // return Pet (model) $response = $pet_api->getPetById($pet_id); - $this->assertSame($response->id, $pet_id); - $this->assertSame($response->name, 'PHP Unit Test'); - $this->assertSame($response->category->id, $pet_id); - $this->assertSame($response->category->name, 'test php category'); - $this->assertSame($response->tags[0]->id, $pet_id); - $this->assertSame($response->tags[0]->name, 'test php tag'); + $this->assertSame($response->getId(), $pet_id); + $this->assertSame($response->getName(), 'PHP Unit Test'); + $this->assertSame($response->getCategory()->getId(), $pet_id); + $this->assertSame($response->getCategory()->getName(), 'test php category'); + $this->assertSame($response->getTags()[0]->getId(), $pet_id); + $this->assertSame($response->getTags()[0]->getName(), 'test php tag'); } // test getPetByStatus and verify by the "id" of the response public function testFindPetByStatus() { // initialize the API client - $api_client = new Swagger\Client\ApiClient('http://petstore.swagger.io/v2'); + $config = (new Swagger\Client\Configuration())->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); $pet_api = new Swagger\Client\Api\PetAPI($api_client); // return Pet (model) $response = $pet_api->findPetsByStatus("available"); @@ -133,30 +121,32 @@ class PetApiTest extends \PHPUnit_Framework_TestCase public function testUpdatePet() { // initialize the API client - $api_client = new Swagger\Client\ApiClient('http://petstore.swagger.io/v2'); + $config = (new Swagger\Client\Configuration())->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); $pet_id = 10001; // ID of pet that needs to be fetched $pet_api = new Swagger\Client\Api\PetAPI($api_client); // create updated pet object $updated_pet = new Swagger\Client\Model\Pet; - $updated_pet->id = $pet_id; - $updated_pet->name = 'updatePet'; // new name - $updated_pet->status = 'pending'; // new status + $updated_pet->setId($pet_id); + $updated_pet->setName('updatePet'); // new name + $updated_pet->setStatus('pending'); // new status // update Pet (model/json) $update_response = $pet_api->updatePet($updated_pet); // return nothing (void) $this->assertSame($update_response, NULL); // verify updated Pet $response = $pet_api->getPetById($pet_id); - $this->assertSame($response->id, $pet_id); - $this->assertSame($response->status, 'pending'); - $this->assertSame($response->name, 'updatePet'); + $this->assertSame($response->getId(), $pet_id); + $this->assertSame($response->getStatus(), 'pending'); + $this->assertSame($response->getName(), 'updatePet'); } // test updatePet and verify by the "id" of the response public function testUpdatePetWithForm() { // initialize the API client - $api_client = new Swagger\Client\ApiClient('http://petstore.swagger.io/v2'); + $config = (new Swagger\Client\Configuration())->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); $pet_id = 10001; // ID of pet that needs to be fetched $pet_api = new Swagger\Client\Api\PetAPI($api_client); // update Pet (form) @@ -164,20 +154,21 @@ class PetApiTest extends \PHPUnit_Framework_TestCase // return nothing (void) $this->assertSame($update_response, NULL); $response = $pet_api->getPetById($pet_id); - $this->assertSame($response->id, $pet_id); - $this->assertSame($response->name, 'update pet with form'); - $this->assertSame($response->status, 'sold'); + $this->assertSame($response->getId(), $pet_id); + $this->assertSame($response->getName(), 'update pet with form'); + $this->assertSame($response->getStatus(), 'sold'); } // test addPet and verify by the "id" and "name" of the response public function testAddPet() { // initialize the API client - $api_client = new Swagger\Client\ApiClient('http://petstore.swagger.io/v2'); + $config = (new Swagger\Client\Configuration())->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); $new_pet_id = 10001; $new_pet = new Swagger\Client\Model\Pet; - $new_pet->id = $new_pet_id; - $new_pet->name = "PHP Unit Test"; + $new_pet->setId($new_pet_id); + $new_pet->setName("PHP Unit Test"); $pet_api = new Swagger\Client\Api\PetAPI($api_client); // add a new pet (model) $add_response = $pet_api->addPet($new_pet); @@ -185,15 +176,16 @@ class PetApiTest extends \PHPUnit_Framework_TestCase $this->assertSame($add_response, NULL); // verify added Pet $response = $pet_api->getPetById($new_pet_id); - $this->assertSame($response->id, $new_pet_id); - $this->assertSame($response->name, 'PHP Unit Test'); + $this->assertSame($response->getId(), $new_pet_id); + $this->assertSame($response->getName(), 'PHP Unit Test'); } // test upload file public function testUploadFile() { // initialize the API client - $api_client = new Swagger\Client\ApiClient('http://petstore.swagger.io/v2'); + $config = (new Swagger\Client\Configuration())->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); $pet_api = new Swagger\Client\Api\PetAPI($api_client); // upload file $pet_id = 10001; @@ -206,7 +198,9 @@ class PetApiTest extends \PHPUnit_Framework_TestCase public function testGetInventory() { // initialize the API client - $api_client = new Swagger\Client\APIClient('http://petstore.swagger.io/v2'); + $config = new Swagger\Client\Configuration(); + $config->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\APIClient($config); $store_api = new Swagger\Client\Api\StoreAPI($api_client); // get inventory $get_response = $store_api->getInventory(); diff --git a/samples/client/petstore/php/SwaggerClient-php/tests/StoreApiTest.php b/samples/client/petstore/php/SwaggerClient-php/tests/StoreApiTest.php index a92149fbaf3..05bd873c993 100644 --- a/samples/client/petstore/php/SwaggerClient-php/tests/StoreApiTest.php +++ b/samples/client/petstore/php/SwaggerClient-php/tests/StoreApiTest.php @@ -1,6 +1,6 @@ setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); + $store_api = new Swagger\Client\Api\StoreAPI($api_client); // get inventory $get_response = $store_api->getInventory(); diff --git a/samples/client/petstore/php/SwaggerClient-php/tests/UserApiTest.php b/samples/client/petstore/php/SwaggerClient-php/tests/UserApiTest.php index 181e8a1249e..3efce8b08ba 100644 --- a/samples/client/petstore/php/SwaggerClient-php/tests/UserApiTest.php +++ b/samples/client/petstore/php/SwaggerClient-php/tests/UserApiTest.php @@ -1,6 +1,6 @@ setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); + $user_api = new Swagger\Client\Api\UserApi($api_client); // login $response = $user_api->loginUser("xxxxx", "yyyyyyyy"); From 6aac24398a3538e664fd56fc5d96b95e5f1ae29d Mon Sep 17 00:00:00 2001 From: wing328 Date: Wed, 24 Jun 2015 14:34:05 +0800 Subject: [PATCH 66/67] update model to support inheritance (#879) --- .../src/main/resources/csharp/model.mustache | 8 ++++---- .../csharp/src/main/csharp/io/swagger/Model/Category.cs | 2 -- .../csharp/src/main/csharp/io/swagger/Model/Order.cs | 2 -- .../csharp/src/main/csharp/io/swagger/Model/Pet.cs | 2 -- .../csharp/src/main/csharp/io/swagger/Model/Tag.cs | 2 -- .../csharp/src/main/csharp/io/swagger/Model/User.cs | 2 -- 6 files changed, 4 insertions(+), 14 deletions(-) diff --git a/modules/swagger-codegen/src/main/resources/csharp/model.mustache b/modules/swagger-codegen/src/main/resources/csharp/model.mustache index 0d86e0e2b99..c0fac63b385 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/model.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/model.mustache @@ -13,7 +13,7 @@ namespace {{packageName}}.Model { /// {{description}} /// [DataContract] - public class {{classname}} { + public class {{classname}}{{#parent}} : {{{parent}}}{{/parent}} { {{#vars}} {{#description}}/* {{{description}}} */{{/description}} [DataMember(Name="{{baseName}}", EmitDefaultValue=false)] @@ -39,11 +39,11 @@ namespace {{packageName}}.Model { /// Get the JSON string presentation of the object /// /// JSON string presentation of the object - public string ToJson() { + public {{#parent}} new {{/parent}}string ToJson() { return JsonConvert.SerializeObject(this, Formatting.Indented); } } - {{/model}} - {{/models}} +{{/model}} +{{/models}} } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Category.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Category.cs index 74121762af9..4a410e8220d 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Category.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Category.cs @@ -49,6 +49,4 @@ namespace IO.Swagger.Model { } } - - } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs index 7451619050c..9e7e706f77e 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Order.cs @@ -77,6 +77,4 @@ namespace IO.Swagger.Model { } } - - } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Pet.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Pet.cs index 0bfba35b1e3..49e6d582f5e 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Pet.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Pet.cs @@ -77,6 +77,4 @@ namespace IO.Swagger.Model { } } - - } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Tag.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Tag.cs index 53901491a47..47c87ae9ef1 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Tag.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/Tag.cs @@ -49,6 +49,4 @@ namespace IO.Swagger.Model { } } - - } diff --git a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/User.cs b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/User.cs index e58d0296a06..f2c3db54608 100644 --- a/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/User.cs +++ b/samples/client/petstore/csharp/src/main/csharp/io/swagger/Model/User.cs @@ -91,6 +91,4 @@ namespace IO.Swagger.Model { } } - - } From 07d5365c5cb3ae2005ffa00eb2e8e6786da38509 Mon Sep 17 00:00:00 2001 From: Tony Tam Date: Thu, 25 Jun 2015 10:17:28 -0700 Subject: [PATCH 67/67] merged from #902, rebuilt client --- .../codegen/languages/PhpClientCodegen.java | 64 +++- .../src/main/resources/php/ApiClient.mustache | 322 +++-------------- .../main/resources/php/ApiException.mustache | 28 +- .../resources/php/ObjectSerializer.mustache | 151 ++++++++ .../src/main/resources/php/api.mustache | 92 +++-- .../src/main/resources/php/autoload.mustache | 4 +- .../src/main/resources/php/composer.mustache | 2 +- .../main/resources/php/configuration.mustache | 241 ++++++++++++- .../src/main/resources/php/model.mustache | 42 ++- .../php/SwaggerClient-php/lib/Api/PetApi.php | 310 +++++++++++------ .../SwaggerClient-php/lib/Api/StoreApi.php | 174 ++++++---- .../php/SwaggerClient-php/lib/Api/UserApi.php | 256 ++++++++------ .../php/SwaggerClient-php/lib/ApiClient.php | 327 +++--------------- .../SwaggerClient-php/lib/ApiException.php | 28 +- .../SwaggerClient-php/lib/Configuration.php | 241 ++++++++++++- .../SwaggerClient-php/lib/Model/Category.php | 60 +++- .../php/SwaggerClient-php/lib/Model/Order.php | 156 ++++++++- .../php/SwaggerClient-php/lib/Model/Pet.php | 156 ++++++++- .../php/SwaggerClient-php/lib/Model/Tag.php | 60 +++- .../php/SwaggerClient-php/lib/Model/User.php | 204 ++++++++++- .../lib/ObjectSerializer.php | 151 ++++++++ .../SwaggerClient-php/tests/PetApiTest.php | 104 +++--- .../SwaggerClient-php/tests/StoreApiTest.php | 7 +- .../SwaggerClient-php/tests/UserApiTest.php | 7 +- 24 files changed, 2145 insertions(+), 1042 deletions(-) create mode 100644 modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache create mode 100644 samples/client/petstore/php/SwaggerClient-php/lib/ObjectSerializer.php diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java index 5bf8400577d..e2ddba4bf34 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/PhpClientCodegen.java @@ -1,5 +1,6 @@ package io.swagger.codegen.languages; +import io.swagger.codegen.CliOption; import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.CodegenType; import io.swagger.codegen.DefaultCodegen; @@ -18,7 +19,9 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { protected String invokerPackage = "Swagger\\Client"; protected String groupId = "swagger"; protected String artifactId = "swagger-client"; + protected String packagePath = "SwaggerClient-php"; protected String artifactVersion = null; + protected String srcBasePath = "lib"; public PhpClientCodegen() { super(); @@ -38,6 +41,7 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { additionalProperties.put("invokerPackage", invokerPackage); additionalProperties.put("modelPackage", modelPackage); additionalProperties.put("apiPackage", apiPackage); + additionalProperties.put("srcBasePath", srcBasePath); additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); additionalProperties.put("groupId", groupId); additionalProperties.put("artifactId", artifactId); @@ -81,16 +85,13 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { typeMapping.put("list", "array"); typeMapping.put("object", "object"); typeMapping.put("DateTime", "\\DateTime"); - - supportingFiles.add(new SupportingFile("composer.mustache", getPackagePath(), "composer.json")); - supportingFiles.add(new SupportingFile("configuration.mustache", toPackagePath(invokerPackage, "lib"), "Configuration.php")); - supportingFiles.add(new SupportingFile("ApiClient.mustache", toPackagePath(invokerPackage, "lib"), "ApiClient.php")); - supportingFiles.add(new SupportingFile("ApiException.mustache", toPackagePath(invokerPackage, "lib"), "ApiException.php")); - supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php")); + + cliOptions.add(new CliOption("packagePath", "main package name for classes")); + cliOptions.add(new CliOption("srcBasePath", "directory directory under packagePath to serve as source root")); } public String getPackagePath() { - return "SwaggerClient-php"; + return packagePath; } public String toPackagePath(String packageName, String basePath) { @@ -134,6 +135,39 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { return "Generates a PHP client library."; } + @Override + public void processOpts() { + super.processOpts(); + + if (additionalProperties.containsKey("packagePath")) { + this.setPackagePath((String) additionalProperties.get("packagePath")); + } + + if (additionalProperties.containsKey("srcBasePath")) { + this.setSrcBasePath((String) additionalProperties.get("srcBasePath")); + } + + if (additionalProperties.containsKey("modelPackage")) { + this.setModelPackage((String) additionalProperties.get("modelPackage")); + } + + if (additionalProperties.containsKey("apiPackage")) { + this.setApiPackage((String) additionalProperties.get("apiPackage")); + } + + additionalProperties.put("srcBasePath", srcBasePath); + additionalProperties.put("modelPackage", modelPackage); + additionalProperties.put("apiPackage", apiPackage); + additionalProperties.put("escapedInvokerPackage", invokerPackage.replace("\\", "\\\\")); + + supportingFiles.add(new SupportingFile("configuration.mustache", toPackagePath(invokerPackage, srcBasePath), "Configuration.php")); + supportingFiles.add(new SupportingFile("ApiClient.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiClient.php")); + supportingFiles.add(new SupportingFile("ApiException.mustache", toPackagePath(invokerPackage, srcBasePath), "ApiException.php")); + supportingFiles.add(new SupportingFile("ObjectSerializer.mustache", toPackagePath(invokerPackage, srcBasePath), "ObjectSerializer.php")); + supportingFiles.add(new SupportingFile("composer.mustache", getPackagePath(), "composer.json")); + supportingFiles.add(new SupportingFile("autoload.mustache", getPackagePath(), "autoload.php")); + } + @Override public String escapeReservedWord(String name) { return "_" + name; @@ -141,11 +175,11 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { @Override public String apiFileFolder() { - return (outputFolder + File.separator + toPackagePath(apiPackage(), "lib")); + return (outputFolder + "/" + toPackagePath(apiPackage(), srcBasePath)); } public String modelFileFolder() { - return (outputFolder + File.separator + toPackagePath(modelPackage(), "lib")); + return (outputFolder + "/" + toPackagePath(modelPackage(), srcBasePath)); } @Override @@ -198,6 +232,17 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { return "null"; } + public void setInvokerPackage(String invokerPackage) { + this.invokerPackage = invokerPackage; + } + + public void setPackagePath(String packagePath) { + this.packagePath = packagePath; + } + + public void setSrcBasePath(String srcBasePath) { + this.srcBasePath = srcBasePath; + } @Override public String toVarName(String name) { @@ -235,5 +280,4 @@ public class PhpClientCodegen extends DefaultCodegen implements CodegenConfig { // should be the same as the model name return toModelName(name); } - } diff --git a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache index 9badb4dbb37..2862a0e0538 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiClient.mustache @@ -25,141 +25,60 @@ class ApiClient { public static $PUT = "PUT"; public static $DELETE = "DELETE"; - /** @var string[] Array of default headers where the key is the header name and the value is the header value */ - private $default_header = array(); + /** @var Configuration */ + protected $config; - /** @var string timeout (second) of the HTTP request, by default set to 0, no timeout */ - protected $curl_timeout = 0; - - /** @var string user agent of the HTTP request, set to "PHP-Swagger" by default */ - protected $user_agent = "PHP-Swagger"; + /** @var ObjectSerializer */ + protected $serializer; /** - * @param string $host Base url of the API server (optional) + * @param Configuration $config config for this ApiClient */ - function __construct($host = null) { - if ($host === null) { - $this->host = '{{basePath}}'; - } else { - $this->host = $host; + function __construct(Configuration $config = null) { + if ($config == null) { + $config = Configuration::getDefaultConfiguration(); } + + $this->config = $config; + $this->serializer = new ObjectSerializer(); } /** - * add default header - * - * @param string $header_name header name (e.g. Token) - * @param string $header_value header value (e.g. 1z8wp3) + * get the config + * @return Configuration */ - public function addDefaultHeader($header_name, $header_value) { - if (!is_string($header_name)) - throw new \InvalidArgumentException('Header name must be a string.'); - - $this->default_header[$header_name] = $header_value; + public function getConfig() { + return $this->config; } /** - * get the default header - * - * @return array default header + * get the serializer + * @return ObjectSerializer */ - public function getDefaultHeader() { - return $this->default_header; + public function getSerializer() { + return $this->serializer; } - /** - * delete the default header based on header name - * - * @param string $header_name header name (e.g. Token) - */ - public function deleteDefaultHeader($header_name) { - unset($this->default_header[$header_name]); - } - - /** - * set the user agent of the api client - * - * @param string $user_agent the user agent of the api client - */ - public function setUserAgent($user_agent) { - if (!is_string($user_agent)) - throw new \InvalidArgumentException('User-agent must be a string.'); - - $this->user_agent= $user_agent; - } - - /** - * get the user agent of the api client - * - * @return string user agent - */ - public function getUserAgent($user_agent) { - return $this->user_agent; - } - - /** - * set the HTTP timeout value - * - * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] - */ - public function setTimeout($seconds) { - if (!is_numeric($seconds) || $seconds < 0) - throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); - - $this->curl_timeout = $seconds; - } - - /** - * get the HTTP timeout value - * - * @return string HTTP timeout value - */ - public function getTimeout() { - return $this->curl_timeout; - } - - /** * Get API key (with prefix if set) - * @param string key name + * @param string $apiKey name of apikey * @return string API key with the prefix */ public function getApiKeyWithPrefix($apiKey) { - if (isset(Configuration::$apiKeyPrefix[$apiKey])) { - return Configuration::$apiKeyPrefix[$apiKey]." ".Configuration::$apiKey[$apiKey]; - } else if (isset(Configuration::$apiKey[$apiKey])) { - return Configuration::$apiKey[$apiKey]; + $prefix = $this->config->getApiKeyPrefix($apiKey); + $apiKey = $this->config->getApiKey($apiKey); + + if (!isset($apiKey)) { + return null; + } + + if (isset($prefix)) { + $keyWithPrefix = $prefix." ".$apiKey; } else { - return; + $keyWithPrefix = $apiKey; } - } - /** - * update hearder and query param based on authentication setting - * - * @param array $headerParams header parameters (by ref) - * @param array $queryParams query parameters (by ref) - * @param array $authSettings array of authentication scheme (e.g ['api_key']) - */ - public function updateParamsForAuth(&$headerParams, &$queryParams, $authSettings) - { - if (count($authSettings) == 0) - return; - - // one endpoint can have more than 1 auth settings - foreach($authSettings as $auth) { - // determine which one to use - switch($auth) { - {{#authMethods}} - case '{{name}}': - {{#isApiKey}}{{#isKeyInHeader}}$headerParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInHeader}}{{#isKeyInQuery}}$queryParams['{{keyParamName}}'] = $this->getApiKeyWithPrefix('{{keyParamName}}');{{/isKeyInQuery}}{{/isApiKey}}{{#isBasic}}$headerParams['Authorization'] = 'Basic '.base64_encode(Configuration::$username.":".Configuration::$password);{{/isBasic}} - {{#isOAuth}}//TODO support oauth{{/isOAuth}} - break; - {{/authMethods}} - default: - //TODO show warning about security definition not found - } - } + return $keyWithPrefix; } /** @@ -168,18 +87,15 @@ class ApiClient { * @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 + * @throws \{{invokerPackage}}\ApiException on a non 2xx response * @return mixed */ - public function callApi($resourcePath, $method, $queryParams, $postData, - $headerParams, $authSettings) { + public function callApi($resourcePath, $method, $queryParams, $postData, $headerParams) { $headers = array(); - # determine authentication setting - $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); - # construct the http header - $headerParams = array_merge((array)$this->default_header, (array)$headerParams); + $headerParams = array_merge((array)$this->config->getDefaultHeaders(), (array)$headerParams); foreach ($headerParams as $key => $val) { $headers[] = "$key: $val"; @@ -190,15 +106,15 @@ class ApiClient { $postData = http_build_query($postData); } else if ((is_object($postData) or is_array($postData)) and !in_array('Content-Type: multipart/form-data', $headers)) { // json model - $postData = json_encode($this->sanitizeForSerialization($postData)); + $postData = json_encode($this->serializer->sanitizeForSerialization($postData)); } - $url = $this->host . $resourcePath; + $url = $this->config->getHost() . $resourcePath; $curl = curl_init(); // set timeout, if needed - if ($this->curl_timeout != 0) { - curl_setopt($curl, CURLOPT_TIMEOUT, $this->curl_timeout); + if ($this->config->getCurlTimeout() != 0) { + curl_setopt($curl, CURLOPT_TIMEOUT, $this->config->getCurlTimeout()); } // return the result on success, rather than just TRUE curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); @@ -227,14 +143,14 @@ class ApiClient { curl_setopt($curl, CURLOPT_URL, $url); // Set user agent - curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent); + curl_setopt($curl, CURLOPT_USERAGENT, $this->config->getUserAgent()); // debugging for curl - if (Configuration::$debug) { - error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, Configuration::$debug_file); + if ($this->config->getDebug()) { + error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, $this->config->getDebugFile()); curl_setopt($curl, CURLOPT_VERBOSE, 1); - curl_setopt($curl, CURLOPT_STDERR, fopen(Configuration::$debug_file, 'a')); + curl_setopt($curl, CURLOPT_STDERR, fopen($this->config->getDebugFile(), 'a')); } else { curl_setopt($curl, CURLOPT_VERBOSE, 0); } @@ -250,8 +166,8 @@ class ApiClient { $response_info = curl_getinfo($curl); // debug HTTP response body - if (Configuration::$debug) { - error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, Configuration::$debug_file); + if ($this->config->getDebug()) { + error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, $this->config->getDebugFile()); } // Handle the response @@ -269,153 +185,13 @@ class ApiClient { 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) { - if ($data->$property !== null) { - $values[$data::$attributeMap[$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 function toPathValue($value) { - return rawurlencode($this->toString($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 function toQueryValue($object) { - if (is_array($object)) { - return implode(',', $object); - } else { - return $this->toString($object); - } - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the header. If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value a string which will be part of the header - * @return string the header string - */ - public function toHeaderValue($value) { - return $this->toString($value); - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the http body (form parameter). If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value the value of the form parameter - * @return string the form string - */ - public function toFormValue($value) { - return $this->toString($value); - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the parameter. If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value the value of the parameter - * @return string the header string - */ - public function toString($value) { - if ($value instanceof \DateTime) { // datetime in ISO8601 format - return $value->format(\DateTime::ISO8601); - } - else { - 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 function deserialize($data, $class) - { - if (null === $data) { - $deserialized = null; - } elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] - $inner = substr($class, 4, -1); - $deserialized = array(); - if(strrpos($inner, ",") !== false) { - $subClass_array = explode(',', $inner, 2); - $subClass = $subClass_array[1]; - foreach ($data as $key => $value) { - $deserialized[$key] = $this->deserialize($value, $subClass); - } - } - } elseif (strcasecmp(substr($class, -2),'[]') == 0) { - $subClass = substr($class, 0, -2); - $values = array(); - foreach ($data as $key => $value) { - $values[] = $this->deserialize($value, $subClass); - } - $deserialized = $values; - } elseif ($class == 'DateTime') { - $deserialized = new \DateTime($data); - } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { - settype($data, $class); - $deserialized = $data; - } else { - $instance = new $class(); - foreach ($instance::$swaggerTypes as $property => $type) { - $original_property_name = $instance::$attributeMap[$property]; - if (isset($original_property_name) && isset($data->$original_property_name)) { - $instance->$property = $this->deserialize($data->$original_property_name, $type); - } - } - $deserialized = $instance; - } - - return $deserialized; - } - /* * return the header 'Accept' based on an array of Accept provided * - * @param array[string] $accept Array of header + * @param string[] $accept Array of header * @return string Accept (e.g. application/json) */ - public function selectHeaderAccept($accept) { + public static function selectHeaderAccept($accept) { if (count($accept) === 0 or (count($accept) === 1 and $accept[0] === '')) { return NULL; } elseif (preg_grep("/application\/json/i", $accept)) { @@ -428,10 +204,10 @@ class ApiClient { /* * return the content type based on an array of content-type provided * - * @param array[string] content_type_array Array fo content-type + * @param string[] content_type_array Array fo content-type * @return string Content-Type (e.g. application/json) */ - public function selectHeaderContentType($content_type) { + public static function selectHeaderContentType($content_type) { if (count($content_type) === 0 or (count($content_type) === 1 and $content_type[0] === '')) { return 'application/json'; } elseif (preg_grep("/application\/json/i", $content_type)) { @@ -440,6 +216,4 @@ class ApiClient { return implode(',', $content_type); } } - } - diff --git a/modules/swagger-codegen/src/main/resources/php/ApiException.mustache b/modules/swagger-codegen/src/main/resources/php/ApiException.mustache index a835d579d32..6d5415f798d 100644 --- a/modules/swagger-codegen/src/main/resources/php/ApiException.mustache +++ b/modules/swagger-codegen/src/main/resources/php/ApiException.mustache @@ -22,15 +22,20 @@ use \Exception; class ApiException extends Exception { /** @var string The HTTP body of the server response. */ - protected $response_body; + protected $responseBody; /** @var string[] The HTTP header of the server response. */ - protected $response_headers; + protected $responseHeaders; + + /** + * The deserialized response object + */ + protected $responseObject; public function __construct($message="", $code=0, $responseHeaders=null, $responseBody=null) { parent::__construct($message, $code); - $this->response_headers = $responseHeaders; - $this->response_body = $responseBody; + $this->responseHeaders = $responseHeaders; + $this->responseBody = $responseBody; } /** @@ -39,7 +44,7 @@ class ApiException extends Exception { * @return string HTTP response header */ public function getResponseHeaders() { - return $this->response_headers; + return $this->responseHeaders; } /** @@ -48,7 +53,18 @@ class ApiException extends Exception { * @return string HTTP response body */ public function getResponseBody() { - return $this->response_body; + return $this->responseBody; } + /** + * sets the deseralized response object (during deserialization) + * @param mixed $obj + */ + public function setResponseObject($obj) { + $this->responseObject = $obj; + } + + public function getResponseObject() { + return $this->responseObject; + } } diff --git a/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache b/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache new file mode 100644 index 00000000000..56a61e97c91 --- /dev/null +++ b/modules/swagger-codegen/src/main/resources/php/ObjectSerializer.mustache @@ -0,0 +1,151 @@ +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) { + $getter = $data::$getters[$property]; + if ($data->$getter() !== null) { + $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$getter()); + } + } + $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 function toPathValue($value) { + return rawurlencode($this->toString($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 function toQueryValue($object) { + if (is_array($object)) { + return implode(',', $object); + } else { + return $this->toString($object); + } + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the header. If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value a string which will be part of the header + * @return string the header string + */ + public function toHeaderValue($value) { + return $this->toString($value); + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the http body (form parameter). If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value the value of the form parameter + * @return string the form string + */ + public function toFormValue($value) { + return $this->toString($value); + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the parameter. If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value the value of the parameter + * @return string the header string + */ + public function toString($value) { + if ($value instanceof \DateTime) { // datetime in ISO8601 format + return $value->format(\DateTime::ISO8601); + } else { + return $value; + } + } + + /** + * Deserialize a JSON string into an object + * + * @param mixed $data object or primitive to be deserialized + * @param string $class class name is passed as a string + * @return object an instance of $class + */ + public function deserialize($data, $class) { + if (null === $data) { + $deserialized = null; + } elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] + $inner = substr($class, 4, -1); + $deserialized = array(); + if(strrpos($inner, ",") !== false) { + $subClass_array = explode(',', $inner, 2); + $subClass = $subClass_array[1]; + foreach ($data as $key => $value) { + $deserialized[$key] = $this->deserialize($value, $subClass); + } + } + } elseif (strcasecmp(substr($class, -2),'[]') == 0) { + $subClass = substr($class, 0, -2); + $values = array(); + foreach ($data as $key => $value) { + $values[] = $this->deserialize($value, $subClass); + } + $deserialized = $values; + } elseif ($class == 'DateTime') { + $deserialized = new \DateTime($data); + } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { + settype($data, $class); + $deserialized = $data; + } else { + $instance = new $class(); + foreach ($instance::$swaggerTypes as $property => $type) { + $propertySetter = $instance::$setters[$property]; + + if (!isset($propertySetter) || !isset($data->{$instance::$attributeMap[$property]})) { + continue; + } + + $propertyValue = $data->{$instance::$attributeMap[$property]}; + if (isset($propertyValue)) { + $instance->$propertySetter($this->deserialize($propertyValue, $type)); + } + } + $deserialized = $instance; + } + + return $deserialized; + } +} \ No newline at end of file diff --git a/modules/swagger-codegen/src/main/resources/php/api.mustache b/modules/swagger-codegen/src/main/resources/php/api.mustache index 3ed7f18c579..cd483ffa881 100644 --- a/modules/swagger-codegen/src/main/resources/php/api.mustache +++ b/modules/swagger-codegen/src/main/resources/php/api.mustache @@ -22,31 +22,29 @@ namespace {{apiPackage}}; -use \{{invokerPackage}}\ApiClient; use \{{invokerPackage}}\Configuration; +use \{{invokerPackage}}\ApiClient; +use \{{invokerPackage}}\ApiException; +use \{{invokerPackage}}\ObjectSerializer; {{#operations}} class {{classname}} { - /** - * @param \{{invokerPackage}}\ApiClient|null $apiClient The api client to use. Defaults to getting it from Configuration - */ - function __construct($apiClient = null) { - if (null === $apiClient) { - if (Configuration::$apiClient === null) { - Configuration::$apiClient = new ApiClient(); // create a new API client if not present - $this->apiClient = Configuration::$apiClient; - } - else - $this->apiClient = Configuration::$apiClient; // use the default one - } else { - $this->apiClient = $apiClient; // use the one provided by the user - } - } - /** @var \{{invokerPackage}}\ApiClient instance of the ApiClient */ private $apiClient; + /** + * @param \{{invokerPackage}}\ApiClient|null $apiClient The api client to use + */ + function __construct($apiClient = null) { + if ($apiClient == null) { + $apiClient = new ApiClient(); + $apiClient->getConfig()->setHost('{{basePath}}'); + } + + $this->apiClient = $apiClient; + } + /** * @return \{{invokerPackage}}\ApiClient get the API client */ @@ -55,10 +53,12 @@ class {{classname}} { } /** - * @param \{{invokerPackage}} $apiClient set the API client + * @param \{{invokerPackage}}\ApiClient $apiClient set the API client + * @return {{classname}} */ - public function setApiClient($apiClient) { + public function setApiClient(ApiClient $apiClient) { $this->apiClient = $apiClient; + return $this; } {{#operation}} @@ -69,6 +69,7 @@ class {{classname}} { * {{#allParams}} * @param {{dataType}} ${{paramName}} {{description}} {{^optional}}(required){{/optional}}{{#optional}}(optional){{/optional}} {{/allParams}} * @return {{#returnType}}{{{returnType}}}{{/returnType}}{{^returnType}}void{{/returnType}} + * @throws \{{invokerPackage}}\ApiException on non-2xx response */ public function {{nickname}}({{#allParams}}${{paramName}}{{#optional}}=null{{/optional}}{{#hasMore}}, {{/hasMore}}{{/allParams}}) { {{#allParams}}{{#required}} @@ -86,28 +87,29 @@ class {{classname}} { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array({{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}})); + $_header_accept = ApiClient::selectHeaderAccept(array({{#produces}}'{{mediaType}}'{{#hasMore}}, {{/hasMore}}{{/produces}})); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array({{#consumes}}'{{mediaType}}'{{#hasMore}},{{/hasMore}}{{/consumes}})); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array({{#consumes}}'{{mediaType}}'{{#hasMore}},{{/hasMore}}{{/consumes}})); {{#queryParams}}// query params if(${{paramName}} !== null) { - $queryParams['{{baseName}}'] = $this->apiClient->toQueryValue(${{paramName}}); + $queryParams['{{baseName}}'] = $this->apiClient->getSerializer()->toQueryValue(${{paramName}}); }{{/queryParams}} {{#headerParams}}// header params if(${{paramName}} !== null) { - $headerParams['{{baseName}}'] = $this->apiClient->toHeaderValue(${{paramName}}); + $headerParams['{{baseName}}'] = $this->apiClient->getSerializer()->toHeaderValue(${{paramName}}); }{{/headerParams}} {{#pathParams}}// path params if(${{paramName}} !== null) { $resourcePath = str_replace("{" . "{{baseName}}" . "}", - $this->apiClient->toPathValue(${{paramName}}), $resourcePath); + $this->apiClient->getSerializer()->toPathValue(${{paramName}}), + $resourcePath); }{{/pathParams}} {{#formParams}}// form params if (${{paramName}} !== null) { - $formParams['{{baseName}}'] = {{#isFile}}'@'.{{/isFile}}$this->apiClient->toFormValue(${{paramName}}); + $formParams['{{baseName}}'] = {{#isFile}}'@' . {{/isFile}}$this->apiClient->getSerializer()->toFormValue(${{paramName}}); }{{/formParams}} {{#bodyParams}}// body params $_tempBody = null; @@ -122,22 +124,38 @@ class {{classname}} { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array({{#authMethods}}'{{name}}'{{#hasMore}}, {{/hasMore}}{{/authMethods}}); - + {{#authMethods}}{{#isApiKey}} + $apiKey = $this->apiClient->getApiKeyWithPrefix('{{keyParamName}}'); + if (isset($apiKey)) { + {{#isKeyInHeader}}$headerParams['{{keyParamName}}'] = $apiKey;{{/isKeyInHeader}}{{#isKeyInQuery}}$queryParams['{{keyParamName}}'] = $apiKey;{{/isKeyInQuery}} + }{{/isApiKey}} + {{#isBasic}}$headerParams['Authorization'] = 'Basic '.base64_encode($this->apiClient->getConfig()->getUsername().":".$this->apiClient->getConfig()->getPassword());{{/isBasic}} + {{#isOAuth}}//TODO support oauth{{/isOAuth}} + {{/authMethods}} // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - {{#returnType}}if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { {{#responses}}{{#dataType}} + case {{code}}: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '{{dataType}}'); + $e->setResponseObject($data); + break;{{/dataType}}{{/responses}} + } + + throw $e; + } + {{#returnType}} + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'{{returnType}}'); - return $responseObject;{{/returnType}} + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'{{returnType}}'); + return $responseObject; + {{/returnType}} } {{/operation}} -{{newline}} -{{/operations}} } +{{/operations}} diff --git a/modules/swagger-codegen/src/main/resources/php/autoload.mustache b/modules/swagger-codegen/src/main/resources/php/autoload.mustache index 4f56a6e20c0..04be6e11992 100644 --- a/modules/swagger-codegen/src/main/resources/php/autoload.mustache +++ b/modules/swagger-codegen/src/main/resources/php/autoload.mustache @@ -4,7 +4,7 @@ * * After registering this autoload function with SPL, the following line * would cause the function to attempt to load the \{{invokerPackage}}\Baz\Qux class - * from /path/to/project/lib/Baz/Qux.php: + * from /path/to/project/{{srcBasePath}}/Baz/Qux.php: * * new \{{invokerPackage}}\Baz\Qux; * @@ -17,7 +17,7 @@ spl_autoload_register(function ($class) { $prefix = '{{escapedInvokerPackage}}\\'; // base directory for the namespace prefix - $base_dir = __DIR__ . '/lib/'; + $base_dir = __DIR__ . '/{{srcBasePath}}/'; // does the class use the namespace prefix? $len = strlen($prefix); diff --git a/modules/swagger-codegen/src/main/resources/php/composer.mustache b/modules/swagger-codegen/src/main/resources/php/composer.mustache index f4e38c84f73..d36267617c4 100644 --- a/modules/swagger-codegen/src/main/resources/php/composer.mustache +++ b/modules/swagger-codegen/src/main/resources/php/composer.mustache @@ -28,6 +28,6 @@ "squizlabs/php_codesniffer": "~2.0" }, "autoload": { - "psr-4": { "{{escapedInvokerPackage}}\\" : "lib/" } + "psr-4": { "{{escapedInvokerPackage}}\\" : "{{srcBasePath}}/" } } } diff --git a/modules/swagger-codegen/src/main/resources/php/configuration.mustache b/modules/swagger-codegen/src/main/resources/php/configuration.mustache index 030910ffca7..b85ad289418 100644 --- a/modules/swagger-codegen/src/main/resources/php/configuration.mustache +++ b/modules/swagger-codegen/src/main/resources/php/configuration.mustache @@ -17,37 +17,250 @@ namespace {{invokerPackage}}; -use \{{invokerPackage}}\ApiClient; - class Configuration { + private static $defaultConfiguration = null; + /** @var string[] Associate array to store API key(s) */ - public static $apiKey = array(); + protected $apiKeys = array(); /** string[] Associate array to store API prefix (e.g. Bearer) */ - public static $apiKeyPrefix = array(); + protected $apiKeyPrefixes = array(); /** @var string Username for HTTP basic authentication */ - public static $username = ''; + protected $username = ''; /** @var string Password for HTTP basic authentication */ - public static $password = ''; + protected $password = ''; /** @var \{{invokerPackage}}\ApiClient The default instance of ApiClient */ - public static $apiClient; + protected $defaultHeaders = array(); + + /** @var string The host */ + protected $host = 'http://localhost'; + + /** @var string timeout (second) of the HTTP request, by default set to 0, no timeout */ + protected $curlTimeout = 0; + + /** @var string user agent of the HTTP request, set to "PHP-Swagger" by default */ + protected $userAgent = "PHP-Swagger"; /** @var bool Debug switch (default set to false) */ - public static $debug = false; + protected $debug = false; /** @var string Debug file location (log to STDOUT by default) */ - public static $debug_file = 'php://output'; + protected $debugFile = 'php://output'; - /* - * manually initalize ApiClient + /** + * @param string $key + * @param string $value + * @return Configuration */ - public static function init() { - if (self::$apiClient === null) - self::$apiClient = new ApiClient(); + public function setApiKey($key, $value) { + $this->apiKeys[$key] = $value; + return $this; } + /** + * @param $key + * @return string + */ + public function getApiKey($key) { + return isset($this->apiKeys[$key]) ? $this->apiKeys[$key] : null; + } + + /** + * @param string $key + * @param string $value + * @return Configuration + */ + public function setApiKeyPrefix($key, $value) { + $this->apiKeyPrefixes[$key] = $value; + return $this; + } + + /** + * @param $key + * @return string + */ + public function getApiKeyPrefix($key) { + return isset($this->apiKeyPrefixes[$key]) ? $this->apiKeyPrefixes[$key] : null; + } + + /** + * @param string $username + * @return Configuration + */ + public function setUsername($username) { + $this->username = $username; + return $this; + } + + /** + * @return string + */ + public function getUsername() { + return $this->username; + } + + /** + * @param string $password + * @return Configuration + */ + public function setPassword($password) { + $this->password = $password; + return $this; + } + + /** + * @return string + */ + public function getPassword() { + return $this->password; + } + + /** + * add default header + * + * @param string $headerName header name (e.g. Token) + * @param string $headerValue header value (e.g. 1z8wp3) + * @return ApiClient + */ + public function addDefaultHeader($headerName, $headerValue) { + if (!is_string($headerName)) { + throw new \InvalidArgumentException('Header name must be a string.'); + } + + $this->defaultHeaders[$headerName] = $headerValue; + return $this; + } + + /** + * get the default header + * + * @return array default header + */ + public function getDefaultHeaders() { + return $this->defaultHeaders; + } + + /** + * delete a default header + * @param string $headerName the header to delete + * @return Configuration + */ + public function deleteDefaultHeader($headerName) { + unset($this->defaultHeaders[$headerName]); + } + + /** + * @param string $host + * @return Configuration + */ + public function setHost($host) { + $this->host = $host; + return $this; + } + + /** + * @return string + */ + public function getHost() { + return $this->host; + } + + /** + * set the user agent of the api client + * + * @param string $userAgent the user agent of the api client + * @return ApiClient + */ + public function setUserAgent($userAgent) { + if (!is_string($userAgent)) { + throw new \InvalidArgumentException('User-agent must be a string.'); + } + + $this->userAgent = $userAgent; + return $this; + } + + /** + * get the user agent of the api client + * + * @return string user agent + */ + public function getUserAgent() { + return $this->userAgent; + } + + /** + * set the HTTP timeout value + * + * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] + * @return ApiClient + */ + public function setCurlTimeout($seconds) { + if (!is_numeric($seconds) || $seconds < 0) { + throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); + } + + $this->curlTimeout = $seconds; + return $this; + } + + /** + * get the HTTP timeout value + * + * @return string HTTP timeout value + */ + public function getCurlTimeout() { + return $this->curlTimeout; + } + + /** + * @param bool $debug + * @return Configuration + */ + public function setDebug($debug) { + $this->debug = $debug; + return $this; + } + + /** + * @return bool + */ + public function getDebug() { + return $this->debug; + } + + /** + * @param string $debugFile + * @return Configuration + */ + public function setDebugFile($debugFile) { + $this->debugFile = $debugFile; + return $this; + } + + /** + * @return string + */ + public function getDebugFile() { + return $this->debugFile; + } + + /** + * @return Configuration + */ + public static function getDefaultConfiguration() { + if (self::$defaultConfiguration == null) { + return new Configuration(); + } + + return self::$defaultConfiguration; + } + + public static function setDefaultConfiguration(Configuration $config) { + self::$defaultConfiguration = $config; + } } diff --git a/modules/swagger-codegen/src/main/resources/php/model.mustache b/modules/swagger-codegen/src/main/resources/php/model.mustache index cc2d57197ab..35795bf8c0b 100644 --- a/modules/swagger-codegen/src/main/resources/php/model.mustache +++ b/modules/swagger-codegen/src/main/resources/php/model.mustache @@ -40,18 +40,48 @@ class {{classname}} implements ArrayAccess { {{#vars}}'{{name}}' => '{{baseName}}'{{#hasMore}}, {{/hasMore}}{{/vars}} ); + + /** @var string[] Array of attributes to setter functions (for deserialization of responses) */ + static $setters = array( + {{#vars}}'{{name}}' => '{{setter}}'{{#hasMore}}, + {{/hasMore}}{{/vars}} + ); + + /** @var string[] Array of attributes to getter functions (for serialization of requests) */ + static $getters = array( + {{#vars}}'{{name}}' => '{{getter}}'{{#hasMore}}, + {{/hasMore}}{{/vars}} + ); + {{#vars}} /** @var {{datatype}} ${{name}} {{#description}}{{{description}}} {{/description}}*/ - public ${{name}}; + protected ${{name}}; {{/vars}} - /** - * @param mixed[] Array of parameters to initialize the object with - */ public function __construct(array $data = null) { - {{#vars}}$this->{{name}} = @$data["{{name}}"];{{#hasMore}} - {{/hasMore}}{{/vars}} + if ($data != null) { + {{#vars}}$this->{{name}} = $data["{{name}}"];{{#hasMore}} + {{/hasMore}}{{/vars}} + } + } + {{#vars}} + /** + * get {{name}} + * @return {{datatype}} + */ + public function {{getter}}() { + return $this->{{name}}; } + /** + * set {{name}} + * @param {{datatype}} ${{name}} + * @return $this + */ + public function {{setter}}(${{name}}) { + $this->{{name}} = ${{name}}; + return $this; + } + {{/vars}} public function offsetExists($offset) { return isset($this->$offset); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php b/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php index 7fe7b70312e..ed5cb6b6110 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Api/PetApi.php @@ -22,30 +22,28 @@ namespace Swagger\Client\Api; -use \Swagger\Client\ApiClient; use \Swagger\Client\Configuration; +use \Swagger\Client\ApiClient; +use \Swagger\Client\ApiException; +use \Swagger\Client\ObjectSerializer; class PetApi { - /** - * @param \Swagger\Client\ApiClient|null $apiClient The api client to use. Defaults to getting it from Configuration - */ - function __construct($apiClient = null) { - if (null === $apiClient) { - if (Configuration::$apiClient === null) { - Configuration::$apiClient = new ApiClient(); // create a new API client if not present - $this->apiClient = Configuration::$apiClient; - } - else - $this->apiClient = Configuration::$apiClient; // use the default one - } else { - $this->apiClient = $apiClient; // use the one provided by the user - } - } - /** @var \Swagger\Client\ApiClient instance of the ApiClient */ private $apiClient; + /** + * @param \Swagger\Client\ApiClient|null $apiClient The api client to use + */ + function __construct($apiClient = null) { + if ($apiClient == null) { + $apiClient = new ApiClient(); + $apiClient->getConfig()->setHost('http://petstore.swagger.io/v2'); + } + + $this->apiClient = $apiClient; + } + /** * @return \Swagger\Client\ApiClient get the API client */ @@ -54,10 +52,12 @@ class PetApi { } /** - * @param \Swagger\Client $apiClient set the API client + * @param \Swagger\Client\ApiClient $apiClient set the API client + * @return PetApi */ - public function setApiClient($apiClient) { + public function setApiClient(ApiClient $apiClient) { $this->apiClient = $apiClient; + return $this; } @@ -68,6 +68,7 @@ class PetApi { * * @param \Swagger\Client\Model\Pet $body Pet object that needs to be added to the store (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function updatePet($body) { @@ -80,11 +81,11 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json','application/xml')); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array('application/json','application/xml')); @@ -103,14 +104,21 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -121,6 +129,7 @@ class PetApi { * * @param \Swagger\Client\Model\Pet $body Pet object that needs to be added to the store (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function addPet($body) { @@ -133,11 +142,11 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/json','application/xml')); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array('application/json','application/xml')); @@ -156,14 +165,21 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -174,6 +190,7 @@ class PetApi { * * @param string[] $status Status values that need to be considered for filter (required) * @return \Swagger\Client\Model\Pet[] + * @throws \Swagger\Client\ApiException on non-2xx response */ public function findPetsByStatus($status) { @@ -186,15 +203,15 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // query params if($status !== null) { - $queryParams['status'] = $this->apiClient->toQueryValue($status); + $queryParams['status'] = $this->apiClient->getSerializer()->toQueryValue($status); } @@ -208,20 +225,33 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Pet[]'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\Pet[]'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\Pet[]'); return $responseObject; + } /** @@ -231,6 +261,7 @@ class PetApi { * * @param string[] $tags Tags to filter by (required) * @return \Swagger\Client\Model\Pet[] + * @throws \Swagger\Client\ApiException on non-2xx response */ public function findPetsByTags($tags) { @@ -243,15 +274,15 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // query params if($tags !== null) { - $queryParams['tags'] = $this->apiClient->toQueryValue($tags); + $queryParams['tags'] = $this->apiClient->getSerializer()->toQueryValue($tags); } @@ -265,20 +296,33 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Pet[]'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\Pet[]'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\Pet[]'); return $responseObject; + } /** @@ -288,6 +332,7 @@ class PetApi { * * @param int $pet_id ID of pet that needs to be fetched (required) * @return \Swagger\Client\Model\Pet + * @throws \Swagger\Client\ApiException on non-2xx response */ public function getPetById($pet_id) { @@ -305,18 +350,19 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($pet_id !== null) { $resourcePath = str_replace("{" . "petId" . "}", - $this->apiClient->toPathValue($pet_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($pet_id), + $resourcePath); } @@ -328,20 +374,40 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('api_key', 'petstore_auth'); - + + $apiKey = $this->apiClient->getApiKeyWithPrefix('api_key'); + if (isset($apiKey)) { + $headerParams['api_key'] = $apiKey; + } + + + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Pet'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\Pet'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\Pet'); return $responseObject; + } /** @@ -353,6 +419,7 @@ class PetApi { * @param string $name Updated name of the pet (required) * @param string $status Updated status of the pet (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function updatePetWithForm($pet_id, $name, $status) { @@ -370,25 +437,26 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('application/x-www-form-urlencoded')); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array('application/x-www-form-urlencoded')); // path params if($pet_id !== null) { $resourcePath = str_replace("{" . "petId" . "}", - $this->apiClient->toPathValue($pet_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($pet_id), + $resourcePath); } // form params if ($name !== null) { - $formParams['name'] = $this->apiClient->toFormValue($name); + $formParams['name'] = $this->apiClient->getSerializer()->toFormValue($name); }// form params if ($status !== null) { - $formParams['status'] = $this->apiClient->toFormValue($status); + $formParams['status'] = $this->apiClient->getSerializer()->toFormValue($status); } @@ -399,14 +467,21 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -418,6 +493,7 @@ class PetApi { * @param string $api_key (required) * @param int $pet_id Pet id to delete (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function deletePet($api_key, $pet_id) { @@ -435,21 +511,22 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // header params if($api_key !== null) { - $headerParams['api_key'] = $this->apiClient->toHeaderValue($api_key); + $headerParams['api_key'] = $this->apiClient->getSerializer()->toHeaderValue($api_key); } // path params if($pet_id !== null) { $resourcePath = str_replace("{" . "petId" . "}", - $this->apiClient->toPathValue($pet_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($pet_id), + $resourcePath); } @@ -461,14 +538,21 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -481,6 +565,7 @@ class PetApi { * @param string $additional_metadata Additional data to pass to server (required) * @param string $file file to upload (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function uploadFile($pet_id, $additional_metadata, $file) { @@ -498,25 +583,26 @@ class PetApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array('multipart/form-data')); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array('multipart/form-data')); // path params if($pet_id !== null) { $resourcePath = str_replace("{" . "petId" . "}", - $this->apiClient->toPathValue($pet_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($pet_id), + $resourcePath); } // form params if ($additional_metadata !== null) { - $formParams['additionalMetadata'] = $this->apiClient->toFormValue($additional_metadata); + $formParams['additionalMetadata'] = $this->apiClient->getSerializer()->toFormValue($additional_metadata); }// form params if ($file !== null) { - $formParams['file'] = '@'.$this->apiClient->toFormValue($file); + $formParams['file'] = '@' . $this->apiClient->getSerializer()->toFormValue($file); } @@ -527,16 +613,22 @@ class PetApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('petstore_auth'); - + + + //TODO support oauth + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } - } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Api/StoreApi.php b/samples/client/petstore/php/SwaggerClient-php/lib/Api/StoreApi.php index 07a922aab0a..237ba3f1acf 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Api/StoreApi.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Api/StoreApi.php @@ -22,30 +22,28 @@ namespace Swagger\Client\Api; -use \Swagger\Client\ApiClient; use \Swagger\Client\Configuration; +use \Swagger\Client\ApiClient; +use \Swagger\Client\ApiException; +use \Swagger\Client\ObjectSerializer; class StoreApi { - /** - * @param \Swagger\Client\ApiClient|null $apiClient The api client to use. Defaults to getting it from Configuration - */ - function __construct($apiClient = null) { - if (null === $apiClient) { - if (Configuration::$apiClient === null) { - Configuration::$apiClient = new ApiClient(); // create a new API client if not present - $this->apiClient = Configuration::$apiClient; - } - else - $this->apiClient = Configuration::$apiClient; // use the default one - } else { - $this->apiClient = $apiClient; // use the one provided by the user - } - } - /** @var \Swagger\Client\ApiClient instance of the ApiClient */ private $apiClient; + /** + * @param \Swagger\Client\ApiClient|null $apiClient The api client to use + */ + function __construct($apiClient = null) { + if ($apiClient == null) { + $apiClient = new ApiClient(); + $apiClient->getConfig()->setHost('http://petstore.swagger.io/v2'); + } + + $this->apiClient = $apiClient; + } + /** * @return \Swagger\Client\ApiClient get the API client */ @@ -54,10 +52,12 @@ class StoreApi { } /** - * @param \Swagger\Client $apiClient set the API client + * @param \Swagger\Client\ApiClient $apiClient set the API client + * @return StoreApi */ - public function setApiClient($apiClient) { + public function setApiClient(ApiClient $apiClient) { $this->apiClient = $apiClient; + return $this; } @@ -67,6 +67,7 @@ class StoreApi { * Returns pet inventories by status * * @return map[string,int] + * @throws \Swagger\Client\ApiException on non-2xx response */ public function getInventory() { @@ -79,11 +80,11 @@ class StoreApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -98,20 +99,37 @@ class StoreApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array('api_key'); - + + $apiKey = $this->apiClient->getApiKeyWithPrefix('api_key'); + if (isset($apiKey)) { + $headerParams['api_key'] = $apiKey; + } + + + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), 'map[string,int]'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'map[string,int]'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'map[string,int]'); return $responseObject; + } /** @@ -121,6 +139,7 @@ class StoreApi { * * @param \Swagger\Client\Model\Order $body order placed for purchasing the pet (required) * @return \Swagger\Client\Model\Order + * @throws \Swagger\Client\ApiException on non-2xx response */ public function placeOrder($body) { @@ -133,11 +152,11 @@ class StoreApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -156,20 +175,30 @@ class StoreApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Order'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\Order'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\Order'); return $responseObject; + } /** @@ -179,6 +208,7 @@ class StoreApi { * * @param string $order_id ID of pet that needs to be fetched (required) * @return \Swagger\Client\Model\Order + * @throws \Swagger\Client\ApiException on non-2xx response */ public function getOrderById($order_id) { @@ -196,18 +226,19 @@ class StoreApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($order_id !== null) { $resourcePath = str_replace("{" . "orderId" . "}", - $this->apiClient->toPathValue($order_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($order_id), + $resourcePath); } @@ -219,20 +250,30 @@ class StoreApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\Order'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\Order'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\Order'); return $responseObject; + } /** @@ -242,6 +283,7 @@ class StoreApi { * * @param string $order_id ID of the order that needs to be deleted (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function deleteOrder($order_id) { @@ -259,18 +301,19 @@ class StoreApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($order_id !== null) { $resourcePath = str_replace("{" . "orderId" . "}", - $this->apiClient->toPathValue($order_id), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($order_id), + $resourcePath); } @@ -282,16 +325,19 @@ class StoreApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } - } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Api/UserApi.php b/samples/client/petstore/php/SwaggerClient-php/lib/Api/UserApi.php index f4d35a3a7a0..1d0765bbb81 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Api/UserApi.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Api/UserApi.php @@ -22,30 +22,28 @@ namespace Swagger\Client\Api; -use \Swagger\Client\ApiClient; use \Swagger\Client\Configuration; +use \Swagger\Client\ApiClient; +use \Swagger\Client\ApiException; +use \Swagger\Client\ObjectSerializer; class UserApi { - /** - * @param \Swagger\Client\ApiClient|null $apiClient The api client to use. Defaults to getting it from Configuration - */ - function __construct($apiClient = null) { - if (null === $apiClient) { - if (Configuration::$apiClient === null) { - Configuration::$apiClient = new ApiClient(); // create a new API client if not present - $this->apiClient = Configuration::$apiClient; - } - else - $this->apiClient = Configuration::$apiClient; // use the default one - } else { - $this->apiClient = $apiClient; // use the one provided by the user - } - } - /** @var \Swagger\Client\ApiClient instance of the ApiClient */ private $apiClient; + /** + * @param \Swagger\Client\ApiClient|null $apiClient The api client to use + */ + function __construct($apiClient = null) { + if ($apiClient == null) { + $apiClient = new ApiClient(); + $apiClient->getConfig()->setHost('http://petstore.swagger.io/v2'); + } + + $this->apiClient = $apiClient; + } + /** * @return \Swagger\Client\ApiClient get the API client */ @@ -54,10 +52,12 @@ class UserApi { } /** - * @param \Swagger\Client $apiClient set the API client + * @param \Swagger\Client\ApiClient $apiClient set the API client + * @return UserApi */ - public function setApiClient($apiClient) { + public function setApiClient(ApiClient $apiClient) { $this->apiClient = $apiClient; + return $this; } @@ -68,6 +68,7 @@ class UserApi { * * @param \Swagger\Client\Model\User $body Created user object (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function createUser($body) { @@ -80,11 +81,11 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -103,14 +104,18 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -121,6 +126,7 @@ class UserApi { * * @param \Swagger\Client\Model\User[] $body List of user object (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function createUsersWithArrayInput($body) { @@ -133,11 +139,11 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -156,14 +162,18 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -174,6 +184,7 @@ class UserApi { * * @param \Swagger\Client\Model\User[] $body List of user object (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function createUsersWithListInput($body) { @@ -186,11 +197,11 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -209,14 +220,18 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -228,6 +243,7 @@ class UserApi { * @param string $username The user name for login (required) * @param string $password The password for login in clear text (required) * @return string + * @throws \Swagger\Client\ApiException on non-2xx response */ public function loginUser($username, $password) { @@ -240,18 +256,18 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // query params if($username !== null) { - $queryParams['username'] = $this->apiClient->toQueryValue($username); + $queryParams['username'] = $this->apiClient->getSerializer()->toQueryValue($username); }// query params if($password !== null) { - $queryParams['password'] = $this->apiClient->toQueryValue($password); + $queryParams['password'] = $this->apiClient->getSerializer()->toQueryValue($password); } @@ -265,20 +281,30 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), 'string'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'string'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'string'); return $responseObject; + } /** @@ -287,6 +313,7 @@ class UserApi { * Logs out current logged in user session * * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function logoutUser() { @@ -299,11 +326,11 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); @@ -318,14 +345,18 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -336,6 +367,7 @@ class UserApi { * * @param string $username The name that needs to be fetched. Use user1 for testing. (required) * @return \Swagger\Client\Model\User + * @throws \Swagger\Client\ApiException on non-2xx response */ public function getUserByName($username) { @@ -353,18 +385,19 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($username !== null) { $resourcePath = str_replace("{" . "username" . "}", - $this->apiClient->toPathValue($username), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($username), + $resourcePath); } @@ -376,20 +409,30 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); - if(! $response) { + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + case 200: + $data = $this->apiClient->getSerializer()->deserialize($e->getResponseBody(), '\Swagger\Client\Model\User'); + $e->setResponseObject($data); + break; + } + + throw $e; + } + + if (!$response) { return null; } - $responseObject = $this->apiClient->deserialize($response,'\Swagger\Client\Model\User'); + $responseObject = $this->apiClient->getSerializer()->deserialize($response,'\Swagger\Client\Model\User'); return $responseObject; + } /** @@ -400,6 +443,7 @@ class UserApi { * @param string $username name that need to be deleted (required) * @param \Swagger\Client\Model\User $body Updated user object (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function updateUser($username, $body) { @@ -417,18 +461,19 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($username !== null) { $resourcePath = str_replace("{" . "username" . "}", - $this->apiClient->toPathValue($username), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($username), + $resourcePath); } // body params @@ -444,14 +489,18 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } @@ -462,6 +511,7 @@ class UserApi { * * @param string $username The name that needs to be deleted (required) * @return void + * @throws \Swagger\Client\ApiException on non-2xx response */ public function deleteUser($username) { @@ -479,18 +529,19 @@ class UserApi { $queryParams = array(); $headerParams = array(); $formParams = array(); - $_header_accept = $this->apiClient->selectHeaderAccept(array('application/json', 'application/xml')); + $_header_accept = ApiClient::selectHeaderAccept(array('application/json', 'application/xml')); if (!is_null($_header_accept)) { $headerParams['Accept'] = $_header_accept; } - $headerParams['Content-Type'] = $this->apiClient->selectHeaderContentType(array()); + $headerParams['Content-Type'] = ApiClient::selectHeaderContentType(array()); // path params if($username !== null) { $resourcePath = str_replace("{" . "username" . "}", - $this->apiClient->toPathValue($username), $resourcePath); + $this->apiClient->getSerializer()->toPathValue($username), + $resourcePath); } @@ -502,16 +553,19 @@ class UserApi { // for HTTP post (form) $httpBody = $formParams; } - - // authentication setting, if any - $authSettings = array(); - + // make the API Call - $response = $this->apiClient->callAPI($resourcePath, $method, - $queryParams, $httpBody, - $headerParams, $authSettings); + try { + $response = $this->apiClient->callAPI($resourcePath, $method, + $queryParams, $httpBody, + $headerParams); + } catch (ApiException $e) { + switch ($e->getCode()) { + } + + throw $e; + } } - } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/ApiClient.php b/samples/client/petstore/php/SwaggerClient-php/lib/ApiClient.php index bb5229fb170..66204f0c4f3 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/ApiClient.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/ApiClient.php @@ -25,146 +25,60 @@ class ApiClient { public static $PUT = "PUT"; public static $DELETE = "DELETE"; - /** @var string[] Array of default headers where the key is the header name and the value is the header value */ - private $default_header = array(); + /** @var Configuration */ + protected $config; - /** @var string timeout (second) of the HTTP request, by default set to 0, no timeout */ - protected $curl_timeout = 0; - - /** @var string user agent of the HTTP request, set to "PHP-Swagger" by default */ - protected $user_agent = "PHP-Swagger"; + /** @var ObjectSerializer */ + protected $serializer; /** - * @param string $host Base url of the API server (optional) + * @param Configuration $config config for this ApiClient */ - function __construct($host = null) { - if ($host === null) { - $this->host = 'http://petstore.swagger.io/v2'; - } else { - $this->host = $host; + function __construct(Configuration $config = null) { + if ($config == null) { + $config = Configuration::getDefaultConfiguration(); } + + $this->config = $config; + $this->serializer = new ObjectSerializer(); } /** - * add default header - * - * @param string $header_name header name (e.g. Token) - * @param string $header_value header value (e.g. 1z8wp3) + * get the config + * @return Configuration */ - public function addDefaultHeader($header_name, $header_value) { - if (!is_string($header_name)) - throw new \InvalidArgumentException('Header name must be a string.'); - - $this->default_header[$header_name] = $header_value; + public function getConfig() { + return $this->config; } /** - * get the default header - * - * @return array default header + * get the serializer + * @return ObjectSerializer */ - public function getDefaultHeader() { - return $this->default_header; + public function getSerializer() { + return $this->serializer; } - /** - * delete the default header based on header name - * - * @param string $header_name header name (e.g. Token) - */ - public function deleteDefaultHeader($header_name) { - unset($this->default_header[$header_name]); - } - - /** - * set the user agent of the api client - * - * @param string $user_agent the user agent of the api client - */ - public function setUserAgent($user_agent) { - if (!is_string($user_agent)) - throw new \InvalidArgumentException('User-agent must be a string.'); - - $this->user_agent= $user_agent; - } - - /** - * get the user agent of the api client - * - * @return string user agent - */ - public function getUserAgent($user_agent) { - return $this->user_agent; - } - - /** - * set the HTTP timeout value - * - * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] - */ - public function setTimeout($seconds) { - if (!is_numeric($seconds) || $seconds < 0) - throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); - - $this->curl_timeout = $seconds; - } - - /** - * get the HTTP timeout value - * - * @return string HTTP timeout value - */ - public function getTimeout() { - return $this->curl_timeout; - } - - /** * Get API key (with prefix if set) - * @param string key name + * @param string $apiKey name of apikey * @return string API key with the prefix */ public function getApiKeyWithPrefix($apiKey) { - if (isset(Configuration::$apiKeyPrefix[$apiKey])) { - return Configuration::$apiKeyPrefix[$apiKey]." ".Configuration::$apiKey[$apiKey]; - } else if (isset(Configuration::$apiKey[$apiKey])) { - return Configuration::$apiKey[$apiKey]; + $prefix = $this->config->getApiKeyPrefix($apiKey); + $apiKey = $this->config->getApiKey($apiKey); + + if (!isset($apiKey)) { + return null; + } + + if (isset($prefix)) { + $keyWithPrefix = $prefix." ".$apiKey; } else { - return; + $keyWithPrefix = $apiKey; } - } - /** - * update hearder and query param based on authentication setting - * - * @param array $headerParams header parameters (by ref) - * @param array $queryParams query parameters (by ref) - * @param array $authSettings array of authentication scheme (e.g ['api_key']) - */ - public function updateParamsForAuth(&$headerParams, &$queryParams, $authSettings) - { - if (count($authSettings) == 0) - return; - - // one endpoint can have more than 1 auth settings - foreach($authSettings as $auth) { - // determine which one to use - switch($auth) { - - case 'api_key': - $headerParams['api_key'] = $this->getApiKeyWithPrefix('api_key'); - - break; - - case 'petstore_auth': - - //TODO support oauth - break; - - default: - //TODO show warning about security definition not found - } - } + return $keyWithPrefix; } /** @@ -173,18 +87,15 @@ class ApiClient { * @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 + * @throws \Swagger\Client\ApiException on a non 2xx response * @return mixed */ - public function callApi($resourcePath, $method, $queryParams, $postData, - $headerParams, $authSettings) { + public function callApi($resourcePath, $method, $queryParams, $postData, $headerParams) { $headers = array(); - # determine authentication setting - $this->updateParamsForAuth($headerParams, $queryParams, $authSettings); - # construct the http header - $headerParams = array_merge((array)$this->default_header, (array)$headerParams); + $headerParams = array_merge((array)$this->config->getDefaultHeaders(), (array)$headerParams); foreach ($headerParams as $key => $val) { $headers[] = "$key: $val"; @@ -195,15 +106,15 @@ class ApiClient { $postData = http_build_query($postData); } else if ((is_object($postData) or is_array($postData)) and !in_array('Content-Type: multipart/form-data', $headers)) { // json model - $postData = json_encode($this->sanitizeForSerialization($postData)); + $postData = json_encode($this->serializer->sanitizeForSerialization($postData)); } - $url = $this->host . $resourcePath; + $url = $this->config->getHost() . $resourcePath; $curl = curl_init(); // set timeout, if needed - if ($this->curl_timeout != 0) { - curl_setopt($curl, CURLOPT_TIMEOUT, $this->curl_timeout); + if ($this->config->getCurlTimeout() != 0) { + curl_setopt($curl, CURLOPT_TIMEOUT, $this->config->getCurlTimeout()); } // return the result on success, rather than just TRUE curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); @@ -232,14 +143,14 @@ class ApiClient { curl_setopt($curl, CURLOPT_URL, $url); // Set user agent - curl_setopt($curl, CURLOPT_USERAGENT, $this->user_agent); + curl_setopt($curl, CURLOPT_USERAGENT, $this->config->getUserAgent()); // debugging for curl - if (Configuration::$debug) { - error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, Configuration::$debug_file); + if ($this->config->getDebug()) { + error_log("[DEBUG] HTTP Request body ~BEGIN~\n".print_r($postData, true)."\n~END~\n", 3, $this->config->getDebugFile()); curl_setopt($curl, CURLOPT_VERBOSE, 1); - curl_setopt($curl, CURLOPT_STDERR, fopen(Configuration::$debug_file, 'a')); + curl_setopt($curl, CURLOPT_STDERR, fopen($this->config->getDebugFile(), 'a')); } else { curl_setopt($curl, CURLOPT_VERBOSE, 0); } @@ -255,8 +166,8 @@ class ApiClient { $response_info = curl_getinfo($curl); // debug HTTP response body - if (Configuration::$debug) { - error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, Configuration::$debug_file); + if ($this->config->getDebug()) { + error_log("[DEBUG] HTTP Response body ~BEGIN~\n".print_r($http_body, true)."\n~END~\n", 3, $this->config->getDebugFile()); } // Handle the response @@ -274,153 +185,13 @@ class ApiClient { 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) { - if ($data->$property !== null) { - $values[$data::$attributeMap[$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 function toPathValue($value) { - return rawurlencode($this->toString($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 function toQueryValue($object) { - if (is_array($object)) { - return implode(',', $object); - } else { - return $this->toString($object); - } - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the header. If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value a string which will be part of the header - * @return string the header string - */ - public function toHeaderValue($value) { - return $this->toString($value); - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the http body (form parameter). If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value the value of the form parameter - * @return string the form string - */ - public function toFormValue($value) { - return $this->toString($value); - } - - /** - * Take value and turn it into a string suitable for inclusion in - * the parameter. If it's a string, pass through unchanged - * If it's a datetime object, format it in ISO8601 - * @param string $value the value of the parameter - * @return string the header string - */ - public function toString($value) { - if ($value instanceof \DateTime) { // datetime in ISO8601 format - return $value->format(\DateTime::ISO8601); - } - else { - 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 function deserialize($data, $class) - { - if (null === $data) { - $deserialized = null; - } elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] - $inner = substr($class, 4, -1); - $deserialized = array(); - if(strrpos($inner, ",") !== false) { - $subClass_array = explode(',', $inner, 2); - $subClass = $subClass_array[1]; - foreach ($data as $key => $value) { - $deserialized[$key] = $this->deserialize($value, $subClass); - } - } - } elseif (strcasecmp(substr($class, -2),'[]') == 0) { - $subClass = substr($class, 0, -2); - $values = array(); - foreach ($data as $key => $value) { - $values[] = $this->deserialize($value, $subClass); - } - $deserialized = $values; - } elseif ($class == 'DateTime') { - $deserialized = new \DateTime($data); - } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { - settype($data, $class); - $deserialized = $data; - } else { - $instance = new $class(); - foreach ($instance::$swaggerTypes as $property => $type) { - $original_property_name = $instance::$attributeMap[$property]; - if (isset($original_property_name) && isset($data->$original_property_name)) { - $instance->$property = $this->deserialize($data->$original_property_name, $type); - } - } - $deserialized = $instance; - } - - return $deserialized; - } - /* * return the header 'Accept' based on an array of Accept provided * - * @param array[string] $accept Array of header + * @param string[] $accept Array of header * @return string Accept (e.g. application/json) */ - public function selectHeaderAccept($accept) { + public static function selectHeaderAccept($accept) { if (count($accept) === 0 or (count($accept) === 1 and $accept[0] === '')) { return NULL; } elseif (preg_grep("/application\/json/i", $accept)) { @@ -433,10 +204,10 @@ class ApiClient { /* * return the content type based on an array of content-type provided * - * @param array[string] content_type_array Array fo content-type + * @param string[] content_type_array Array fo content-type * @return string Content-Type (e.g. application/json) */ - public function selectHeaderContentType($content_type) { + public static function selectHeaderContentType($content_type) { if (count($content_type) === 0 or (count($content_type) === 1 and $content_type[0] === '')) { return 'application/json'; } elseif (preg_grep("/application\/json/i", $content_type)) { @@ -445,6 +216,4 @@ class ApiClient { return implode(',', $content_type); } } - } - diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php b/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php index 5f3b1812261..51774137aed 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/ApiException.php @@ -22,15 +22,20 @@ use \Exception; class ApiException extends Exception { /** @var string The HTTP body of the server response. */ - protected $response_body; + protected $responseBody; /** @var string[] The HTTP header of the server response. */ - protected $response_headers; + protected $responseHeaders; + + /** + * The deserialized response object + */ + protected $responseObject; public function __construct($message="", $code=0, $responseHeaders=null, $responseBody=null) { parent::__construct($message, $code); - $this->response_headers = $responseHeaders; - $this->response_body = $responseBody; + $this->responseHeaders = $responseHeaders; + $this->responseBody = $responseBody; } /** @@ -39,7 +44,7 @@ class ApiException extends Exception { * @return string HTTP response header */ public function getResponseHeaders() { - return $this->response_headers; + return $this->responseHeaders; } /** @@ -48,7 +53,18 @@ class ApiException extends Exception { * @return string HTTP response body */ public function getResponseBody() { - return $this->response_body; + return $this->responseBody; } + /** + * sets the deseralized response object (during deserialization) + * @param mixed $obj + */ + public function setResponseObject($obj) { + $this->responseObject = $obj; + } + + public function getResponseObject() { + return $this->responseObject; + } } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php index e6381781bb0..a407fe4dd49 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Configuration.php @@ -17,37 +17,250 @@ namespace Swagger\Client; -use \Swagger\Client\ApiClient; - class Configuration { + private static $defaultConfiguration = null; + /** @var string[] Associate array to store API key(s) */ - public static $apiKey = array(); + protected $apiKeys = array(); /** string[] Associate array to store API prefix (e.g. Bearer) */ - public static $apiKeyPrefix = array(); + protected $apiKeyPrefixes = array(); /** @var string Username for HTTP basic authentication */ - public static $username = ''; + protected $username = ''; /** @var string Password for HTTP basic authentication */ - public static $password = ''; + protected $password = ''; /** @var \Swagger\Client\ApiClient The default instance of ApiClient */ - public static $apiClient; + protected $defaultHeaders = array(); + + /** @var string The host */ + protected $host = 'http://localhost'; + + /** @var string timeout (second) of the HTTP request, by default set to 0, no timeout */ + protected $curlTimeout = 0; + + /** @var string user agent of the HTTP request, set to "PHP-Swagger" by default */ + protected $userAgent = "PHP-Swagger"; /** @var bool Debug switch (default set to false) */ - public static $debug = false; + protected $debug = false; /** @var string Debug file location (log to STDOUT by default) */ - public static $debug_file = 'php://output'; + protected $debugFile = 'php://output'; - /* - * manually initalize ApiClient + /** + * @param string $key + * @param string $value + * @return Configuration */ - public static function init() { - if (self::$apiClient === null) - self::$apiClient = new ApiClient(); + public function setApiKey($key, $value) { + $this->apiKeys[$key] = $value; + return $this; } + /** + * @param $key + * @return string + */ + public function getApiKey($key) { + return isset($this->apiKeys[$key]) ? $this->apiKeys[$key] : null; + } + + /** + * @param string $key + * @param string $value + * @return Configuration + */ + public function setApiKeyPrefix($key, $value) { + $this->apiKeyPrefixes[$key] = $value; + return $this; + } + + /** + * @param $key + * @return string + */ + public function getApiKeyPrefix($key) { + return isset($this->apiKeyPrefixes[$key]) ? $this->apiKeyPrefixes[$key] : null; + } + + /** + * @param string $username + * @return Configuration + */ + public function setUsername($username) { + $this->username = $username; + return $this; + } + + /** + * @return string + */ + public function getUsername() { + return $this->username; + } + + /** + * @param string $password + * @return Configuration + */ + public function setPassword($password) { + $this->password = $password; + return $this; + } + + /** + * @return string + */ + public function getPassword() { + return $this->password; + } + + /** + * add default header + * + * @param string $headerName header name (e.g. Token) + * @param string $headerValue header value (e.g. 1z8wp3) + * @return ApiClient + */ + public function addDefaultHeader($headerName, $headerValue) { + if (!is_string($headerName)) { + throw new \InvalidArgumentException('Header name must be a string.'); + } + + $this->defaultHeaders[$headerName] = $headerValue; + return $this; + } + + /** + * get the default header + * + * @return array default header + */ + public function getDefaultHeaders() { + return $this->defaultHeaders; + } + + /** + * delete a default header + * @param string $headerName the header to delete + * @return Configuration + */ + public function deleteDefaultHeader($headerName) { + unset($this->defaultHeaders[$headerName]); + } + + /** + * @param string $host + * @return Configuration + */ + public function setHost($host) { + $this->host = $host; + return $this; + } + + /** + * @return string + */ + public function getHost() { + return $this->host; + } + + /** + * set the user agent of the api client + * + * @param string $userAgent the user agent of the api client + * @return ApiClient + */ + public function setUserAgent($userAgent) { + if (!is_string($userAgent)) { + throw new \InvalidArgumentException('User-agent must be a string.'); + } + + $this->userAgent = $userAgent; + return $this; + } + + /** + * get the user agent of the api client + * + * @return string user agent + */ + public function getUserAgent() { + return $this->userAgent; + } + + /** + * set the HTTP timeout value + * + * @param integer $seconds Number of seconds before timing out [set to 0 for no timeout] + * @return ApiClient + */ + public function setCurlTimeout($seconds) { + if (!is_numeric($seconds) || $seconds < 0) { + throw new \InvalidArgumentException('Timeout value must be numeric and a non-negative number.'); + } + + $this->curlTimeout = $seconds; + return $this; + } + + /** + * get the HTTP timeout value + * + * @return string HTTP timeout value + */ + public function getCurlTimeout() { + return $this->curlTimeout; + } + + /** + * @param bool $debug + * @return Configuration + */ + public function setDebug($debug) { + $this->debug = $debug; + return $this; + } + + /** + * @return bool + */ + public function getDebug() { + return $this->debug; + } + + /** + * @param string $debugFile + * @return Configuration + */ + public function setDebugFile($debugFile) { + $this->debugFile = $debugFile; + return $this; + } + + /** + * @return string + */ + public function getDebugFile() { + return $this->debugFile; + } + + /** + * @return Configuration + */ + public static function getDefaultConfiguration() { + if (self::$defaultConfiguration == null) { + return new Configuration(); + } + + return self::$defaultConfiguration; + } + + public static function setDefaultConfiguration(Configuration $config) { + self::$defaultConfiguration = $config; + } } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Category.php b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Category.php index 750a8fee5df..75aaf2eeead 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Category.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Category.php @@ -38,21 +38,69 @@ class Category implements ArrayAccess { 'id' => 'id', 'name' => 'name' ); + + /** @var string[] Array of attributes to setter functions (for deserialization of responses) */ + static $setters = array( + 'id' => 'setId', + 'name' => 'setName' + ); + + /** @var string[] Array of attributes to getter functions (for serialization of requests) */ + static $getters = array( + 'id' => 'getId', + 'name' => 'getName' + ); + /** @var int $id */ - public $id; + protected $id; /** @var string $name */ - public $name; + protected $name; + + public function __construct(array $data = null) { + if ($data != null) { + $this->id = $data["id"]; + $this->name = $data["name"]; + } + } /** - * @param mixed[] Array of parameters to initialize the object with + * get id + * @return int */ - public function __construct(array $data = null) { - $this->id = @$data["id"]; - $this->name = @$data["name"]; + public function getId() { + return $this->id; } + /** + * set id + * @param int $id + * @return $this + */ + public function setId($id) { + $this->id = $id; + return $this; + } + + /** + * get name + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * set name + * @param string $name + * @return $this + */ + public function setName($name) { + $this->name = $name; + return $this; + } + public function offsetExists($offset) { return isset($this->$offset); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Order.php b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Order.php index 64552afb763..c7a433c3d8c 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Order.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Order.php @@ -46,37 +46,165 @@ class Order implements ArrayAccess { 'status' => 'status', 'complete' => 'complete' ); + + /** @var string[] Array of attributes to setter functions (for deserialization of responses) */ + static $setters = array( + 'id' => 'setId', + 'pet_id' => 'setPetId', + 'quantity' => 'setQuantity', + 'ship_date' => 'setShipDate', + 'status' => 'setStatus', + 'complete' => 'setComplete' + ); + + /** @var string[] Array of attributes to getter functions (for serialization of requests) */ + static $getters = array( + 'id' => 'getId', + 'pet_id' => 'getPetId', + 'quantity' => 'getQuantity', + 'ship_date' => 'getShipDate', + 'status' => 'getStatus', + 'complete' => 'getComplete' + ); + /** @var int $id */ - public $id; + protected $id; /** @var int $pet_id */ - public $pet_id; + protected $pet_id; /** @var int $quantity */ - public $quantity; + protected $quantity; /** @var \DateTime $ship_date */ - public $ship_date; + protected $ship_date; /** @var string $status Order Status */ - public $status; + protected $status; /** @var bool $complete */ - public $complete; + protected $complete; + + public function __construct(array $data = null) { + if ($data != null) { + $this->id = $data["id"]; + $this->pet_id = $data["pet_id"]; + $this->quantity = $data["quantity"]; + $this->ship_date = $data["ship_date"]; + $this->status = $data["status"]; + $this->complete = $data["complete"]; + } + } /** - * @param mixed[] Array of parameters to initialize the object with + * get id + * @return int */ - public function __construct(array $data = null) { - $this->id = @$data["id"]; - $this->pet_id = @$data["pet_id"]; - $this->quantity = @$data["quantity"]; - $this->ship_date = @$data["ship_date"]; - $this->status = @$data["status"]; - $this->complete = @$data["complete"]; + public function getId() { + return $this->id; } + /** + * set id + * @param int $id + * @return $this + */ + public function setId($id) { + $this->id = $id; + return $this; + } + + /** + * get pet_id + * @return int + */ + public function getPetId() { + return $this->pet_id; + } + + /** + * set pet_id + * @param int $pet_id + * @return $this + */ + public function setPetId($pet_id) { + $this->pet_id = $pet_id; + return $this; + } + + /** + * get quantity + * @return int + */ + public function getQuantity() { + return $this->quantity; + } + + /** + * set quantity + * @param int $quantity + * @return $this + */ + public function setQuantity($quantity) { + $this->quantity = $quantity; + return $this; + } + + /** + * get ship_date + * @return \DateTime + */ + public function getShipDate() { + return $this->ship_date; + } + + /** + * set ship_date + * @param \DateTime $ship_date + * @return $this + */ + public function setShipDate($ship_date) { + $this->ship_date = $ship_date; + return $this; + } + + /** + * get status + * @return string + */ + public function getStatus() { + return $this->status; + } + + /** + * set status + * @param string $status + * @return $this + */ + public function setStatus($status) { + $this->status = $status; + return $this; + } + + /** + * get complete + * @return bool + */ + public function getComplete() { + return $this->complete; + } + + /** + * set complete + * @param bool $complete + * @return $this + */ + public function setComplete($complete) { + $this->complete = $complete; + return $this; + } + public function offsetExists($offset) { return isset($this->$offset); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Pet.php b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Pet.php index ef2a4c76a0d..cbe27e1fce9 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Pet.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Pet.php @@ -46,37 +46,165 @@ class Pet implements ArrayAccess { 'tags' => 'tags', 'status' => 'status' ); + + /** @var string[] Array of attributes to setter functions (for deserialization of responses) */ + static $setters = array( + 'id' => 'setId', + 'category' => 'setCategory', + 'name' => 'setName', + 'photo_urls' => 'setPhotoUrls', + 'tags' => 'setTags', + 'status' => 'setStatus' + ); + + /** @var string[] Array of attributes to getter functions (for serialization of requests) */ + static $getters = array( + 'id' => 'getId', + 'category' => 'getCategory', + 'name' => 'getName', + 'photo_urls' => 'getPhotoUrls', + 'tags' => 'getTags', + 'status' => 'getStatus' + ); + /** @var int $id */ - public $id; + protected $id; /** @var \Swagger\Client\Model\Category $category */ - public $category; + protected $category; /** @var string $name */ - public $name; + protected $name; /** @var string[] $photo_urls */ - public $photo_urls; + protected $photo_urls; /** @var \Swagger\Client\Model\Tag[] $tags */ - public $tags; + protected $tags; /** @var string $status pet status in the store */ - public $status; + protected $status; + + public function __construct(array $data = null) { + if ($data != null) { + $this->id = $data["id"]; + $this->category = $data["category"]; + $this->name = $data["name"]; + $this->photo_urls = $data["photo_urls"]; + $this->tags = $data["tags"]; + $this->status = $data["status"]; + } + } /** - * @param mixed[] Array of parameters to initialize the object with + * get id + * @return int */ - public function __construct(array $data = null) { - $this->id = @$data["id"]; - $this->category = @$data["category"]; - $this->name = @$data["name"]; - $this->photo_urls = @$data["photo_urls"]; - $this->tags = @$data["tags"]; - $this->status = @$data["status"]; + public function getId() { + return $this->id; } + /** + * set id + * @param int $id + * @return $this + */ + public function setId($id) { + $this->id = $id; + return $this; + } + + /** + * get category + * @return \Swagger\Client\Model\Category + */ + public function getCategory() { + return $this->category; + } + + /** + * set category + * @param \Swagger\Client\Model\Category $category + * @return $this + */ + public function setCategory($category) { + $this->category = $category; + return $this; + } + + /** + * get name + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * set name + * @param string $name + * @return $this + */ + public function setName($name) { + $this->name = $name; + return $this; + } + + /** + * get photo_urls + * @return string[] + */ + public function getPhotoUrls() { + return $this->photo_urls; + } + + /** + * set photo_urls + * @param string[] $photo_urls + * @return $this + */ + public function setPhotoUrls($photo_urls) { + $this->photo_urls = $photo_urls; + return $this; + } + + /** + * get tags + * @return \Swagger\Client\Model\Tag[] + */ + public function getTags() { + return $this->tags; + } + + /** + * set tags + * @param \Swagger\Client\Model\Tag[] $tags + * @return $this + */ + public function setTags($tags) { + $this->tags = $tags; + return $this; + } + + /** + * get status + * @return string + */ + public function getStatus() { + return $this->status; + } + + /** + * set status + * @param string $status + * @return $this + */ + public function setStatus($status) { + $this->status = $status; + return $this; + } + public function offsetExists($offset) { return isset($this->$offset); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Tag.php b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Tag.php index 5959cb20a6a..3fd785f001b 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Model/Tag.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Model/Tag.php @@ -38,21 +38,69 @@ class Tag implements ArrayAccess { 'id' => 'id', 'name' => 'name' ); + + /** @var string[] Array of attributes to setter functions (for deserialization of responses) */ + static $setters = array( + 'id' => 'setId', + 'name' => 'setName' + ); + + /** @var string[] Array of attributes to getter functions (for serialization of requests) */ + static $getters = array( + 'id' => 'getId', + 'name' => 'getName' + ); + /** @var int $id */ - public $id; + protected $id; /** @var string $name */ - public $name; + protected $name; + + public function __construct(array $data = null) { + if ($data != null) { + $this->id = $data["id"]; + $this->name = $data["name"]; + } + } /** - * @param mixed[] Array of parameters to initialize the object with + * get id + * @return int */ - public function __construct(array $data = null) { - $this->id = @$data["id"]; - $this->name = @$data["name"]; + public function getId() { + return $this->id; } + /** + * set id + * @param int $id + * @return $this + */ + public function setId($id) { + $this->id = $id; + return $this; + } + + /** + * get name + * @return string + */ + public function getName() { + return $this->name; + } + + /** + * set name + * @param string $name + * @return $this + */ + public function setName($name) { + $this->name = $name; + return $this; + } + public function offsetExists($offset) { return isset($this->$offset); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/Model/User.php b/samples/client/petstore/php/SwaggerClient-php/lib/Model/User.php index 1bfb7f332db..2bb31056bde 100644 --- a/samples/client/petstore/php/SwaggerClient-php/lib/Model/User.php +++ b/samples/client/petstore/php/SwaggerClient-php/lib/Model/User.php @@ -50,45 +50,213 @@ class User implements ArrayAccess { 'phone' => 'phone', 'user_status' => 'userStatus' ); + + /** @var string[] Array of attributes to setter functions (for deserialization of responses) */ + static $setters = array( + 'id' => 'setId', + 'username' => 'setUsername', + 'first_name' => 'setFirstName', + 'last_name' => 'setLastName', + 'email' => 'setEmail', + 'password' => 'setPassword', + 'phone' => 'setPhone', + 'user_status' => 'setUserStatus' + ); + + /** @var string[] Array of attributes to getter functions (for serialization of requests) */ + static $getters = array( + 'id' => 'getId', + 'username' => 'getUsername', + 'first_name' => 'getFirstName', + 'last_name' => 'getLastName', + 'email' => 'getEmail', + 'password' => 'getPassword', + 'phone' => 'getPhone', + 'user_status' => 'getUserStatus' + ); + /** @var int $id */ - public $id; + protected $id; /** @var string $username */ - public $username; + protected $username; /** @var string $first_name */ - public $first_name; + protected $first_name; /** @var string $last_name */ - public $last_name; + protected $last_name; /** @var string $email */ - public $email; + protected $email; /** @var string $password */ - public $password; + protected $password; /** @var string $phone */ - public $phone; + protected $phone; /** @var int $user_status User Status */ - public $user_status; + protected $user_status; + + public function __construct(array $data = null) { + if ($data != null) { + $this->id = $data["id"]; + $this->username = $data["username"]; + $this->first_name = $data["first_name"]; + $this->last_name = $data["last_name"]; + $this->email = $data["email"]; + $this->password = $data["password"]; + $this->phone = $data["phone"]; + $this->user_status = $data["user_status"]; + } + } /** - * @param mixed[] Array of parameters to initialize the object with + * get id + * @return int */ - public function __construct(array $data = null) { - $this->id = @$data["id"]; - $this->username = @$data["username"]; - $this->first_name = @$data["first_name"]; - $this->last_name = @$data["last_name"]; - $this->email = @$data["email"]; - $this->password = @$data["password"]; - $this->phone = @$data["phone"]; - $this->user_status = @$data["user_status"]; + public function getId() { + return $this->id; } + /** + * set id + * @param int $id + * @return $this + */ + public function setId($id) { + $this->id = $id; + return $this; + } + + /** + * get username + * @return string + */ + public function getUsername() { + return $this->username; + } + + /** + * set username + * @param string $username + * @return $this + */ + public function setUsername($username) { + $this->username = $username; + return $this; + } + + /** + * get first_name + * @return string + */ + public function getFirstName() { + return $this->first_name; + } + + /** + * set first_name + * @param string $first_name + * @return $this + */ + public function setFirstName($first_name) { + $this->first_name = $first_name; + return $this; + } + + /** + * get last_name + * @return string + */ + public function getLastName() { + return $this->last_name; + } + + /** + * set last_name + * @param string $last_name + * @return $this + */ + public function setLastName($last_name) { + $this->last_name = $last_name; + return $this; + } + + /** + * get email + * @return string + */ + public function getEmail() { + return $this->email; + } + + /** + * set email + * @param string $email + * @return $this + */ + public function setEmail($email) { + $this->email = $email; + return $this; + } + + /** + * get password + * @return string + */ + public function getPassword() { + return $this->password; + } + + /** + * set password + * @param string $password + * @return $this + */ + public function setPassword($password) { + $this->password = $password; + return $this; + } + + /** + * get phone + * @return string + */ + public function getPhone() { + return $this->phone; + } + + /** + * set phone + * @param string $phone + * @return $this + */ + public function setPhone($phone) { + $this->phone = $phone; + return $this; + } + + /** + * get user_status + * @return int + */ + public function getUserStatus() { + return $this->user_status; + } + + /** + * set user_status + * @param int $user_status + * @return $this + */ + public function setUserStatus($user_status) { + $this->user_status = $user_status; + return $this; + } + public function offsetExists($offset) { return isset($this->$offset); } diff --git a/samples/client/petstore/php/SwaggerClient-php/lib/ObjectSerializer.php b/samples/client/petstore/php/SwaggerClient-php/lib/ObjectSerializer.php new file mode 100644 index 00000000000..802a49bc01a --- /dev/null +++ b/samples/client/petstore/php/SwaggerClient-php/lib/ObjectSerializer.php @@ -0,0 +1,151 @@ +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) { + $getter = $data::$getters[$property]; + if ($data->$getter() !== null) { + $values[$data::$attributeMap[$property]] = $this->sanitizeForSerialization($data->$getter()); + } + } + $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 function toPathValue($value) { + return rawurlencode($this->toString($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 function toQueryValue($object) { + if (is_array($object)) { + return implode(',', $object); + } else { + return $this->toString($object); + } + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the header. If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value a string which will be part of the header + * @return string the header string + */ + public function toHeaderValue($value) { + return $this->toString($value); + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the http body (form parameter). If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value the value of the form parameter + * @return string the form string + */ + public function toFormValue($value) { + return $this->toString($value); + } + + /** + * Take value and turn it into a string suitable for inclusion in + * the parameter. If it's a string, pass through unchanged + * If it's a datetime object, format it in ISO8601 + * @param string $value the value of the parameter + * @return string the header string + */ + public function toString($value) { + if ($value instanceof \DateTime) { // datetime in ISO8601 format + return $value->format(\DateTime::ISO8601); + } else { + return $value; + } + } + + /** + * Deserialize a JSON string into an object + * + * @param mixed $data object or primitive to be deserialized + * @param string $class class name is passed as a string + * @return object an instance of $class + */ + public function deserialize($data, $class) { + if (null === $data) { + $deserialized = null; + } elseif (substr($class, 0, 4) == 'map[') { # for associative array e.g. map[string,int] + $inner = substr($class, 4, -1); + $deserialized = array(); + if(strrpos($inner, ",") !== false) { + $subClass_array = explode(',', $inner, 2); + $subClass = $subClass_array[1]; + foreach ($data as $key => $value) { + $deserialized[$key] = $this->deserialize($value, $subClass); + } + } + } elseif (strcasecmp(substr($class, -2),'[]') == 0) { + $subClass = substr($class, 0, -2); + $values = array(); + foreach ($data as $key => $value) { + $values[] = $this->deserialize($value, $subClass); + } + $deserialized = $values; + } elseif ($class == 'DateTime') { + $deserialized = new \DateTime($data); + } elseif (in_array($class, array('string', 'int', 'float', 'double', 'bool', 'object'))) { + settype($data, $class); + $deserialized = $data; + } else { + $instance = new $class(); + foreach ($instance::$swaggerTypes as $property => $type) { + $propertySetter = $instance::$setters[$property]; + + if (!isset($propertySetter) || !isset($data->{$instance::$attributeMap[$property]})) { + continue; + } + + $propertyValue = $data->{$instance::$attributeMap[$property]}; + if (isset($propertyValue)) { + $instance->$propertySetter($this->deserialize($propertyValue, $type)); + } + } + $deserialized = $instance; + } + + return $deserialized; + } +} \ No newline at end of file diff --git a/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php b/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php index 131a79dba92..3ac28772291 100644 --- a/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php +++ b/samples/client/petstore/php/SwaggerClient-php/tests/PetApiTest.php @@ -22,19 +22,19 @@ class PetApiTest extends \PHPUnit_Framework_TestCase // new pet $new_pet_id = 10005; $new_pet = new Swagger\Client\Model\Pet; - $new_pet->id = $new_pet_id; - $new_pet->name = "PHP Unit Test"; + $new_pet->setId($new_pet_id); + $new_pet->setName("PHP Unit Test"); // new tag $tag= new Swagger\Client\Model\Tag; - $tag->id = $new_pet_id; // use the same id as pet - $tag->name = "test php tag"; + $tag->setId($new_pet_id); // use the same id as pet + $tag->setName("test php tag"); // new category $category = new Swagger\Client\Model\Category; - $category->id = $new_pet_id; // use the same id as pet - $category->name = "test php category"; + $category->setId($new_pet_id); // use the same id as pet + $category->setName("test php category"); - $new_pet->tags = array($tag); - $new_pet->category = $category; + $new_pet->setTags(array($tag)); + $new_pet->setCategory($category); $pet_api = new Swagger\Client\Api\PetAPI(); // add a new pet (model) @@ -56,65 +56,53 @@ class PetApiTest extends \PHPUnit_Framework_TestCase $this->assertSame('application/yaml,application/xml', $api_client->selectHeaderContentType(array('application/yaml','application/xml'))); // test addDefaultHeader and getDefaultHeader - $api_client->addDefaultHeader('test1', 'value1'); - $api_client->addDefaultHeader('test2', 200); - $defaultHeader = $api_client->getDefaultHeader(); + $api_client->getConfig()->addDefaultHeader('test1', 'value1'); + $api_client->getConfig()->addDefaultHeader('test2', 200); + $defaultHeader = $api_client->getConfig()->getDefaultHeaders(); $this->assertSame('value1', $defaultHeader['test1']); $this->assertSame(200, $defaultHeader['test2']); // test deleteDefaultHeader - $api_client->deleteDefaultHeader('test2'); - $defaultHeader = $api_client->getDefaultHeader(); + $api_client->getConfig()->deleteDefaultHeader('test2'); + $defaultHeader = $api_client->getConfig()->getDefaultHeaders(); $this->assertFalse(isset($defaultHeader['test2'])); - $pet_api = new Swagger\Client\Api\PetAPI(); $pet_api2 = new Swagger\Client\Api\PetAPI(); $apiClient3 = new Swagger\Client\ApiClient(); - $apiClient3->setUserAgent = 'api client 3'; + $apiClient3->getConfig()->setUserAgent('api client 3'); $apiClient4 = new Swagger\Client\ApiClient(); - $apiClient4->setUserAgent = 'api client 4'; + $apiClient4->getConfig()->setUserAgent('api client 4'); $pet_api3 = new Swagger\Client\Api\PetAPI($apiClient3); - // same default api client - $this->assertSame($pet_api->getApiClient(), $pet_api2->getApiClient()); - // confirm using the default api client in the Configuration - $this->assertSame($pet_api->getApiClient(), Swagger\Client\Configuration::$apiClient); // 2 different api clients are not the same $this->assertNotEquals($apiClient3, $apiClient4); - // customized pet api not using the default (configuration) api client - $this->assertNotEquals($pet_api3->getApiClient(), Swagger\Client\Configuration::$apiClient); // customied pet api not using the old pet api's api client $this->assertNotEquals($pet_api2->getApiClient(), $pet_api3->getApiClient()); - - // both pet api and pet api2 share the same api client and confirm using timeout value - $pet_api->getApiClient()->setTimeout(999); - $this->assertSame(999, $pet_api2->getApiClient()->getTimeout()); - } // test getPetById with a Pet object (id 10005) public function testGetPetById() { // initialize the API client without host - $api_client = new Swagger\Client\ApiClient(); - Swagger\Client\Configuration::$apiKey['api_key'] = '111222333444555'; $pet_id = 10005; // ID of pet that needs to be fetched - $pet_api = new Swagger\Client\Api\PetAPI($api_client); + $pet_api = new Swagger\Client\Api\PetAPI(); + $pet_api->getApiClient()->getConfig()->setApiKey('api_key', '111222333444555'); // return Pet (model) $response = $pet_api->getPetById($pet_id); - $this->assertSame($response->id, $pet_id); - $this->assertSame($response->name, 'PHP Unit Test'); - $this->assertSame($response->category->id, $pet_id); - $this->assertSame($response->category->name, 'test php category'); - $this->assertSame($response->tags[0]->id, $pet_id); - $this->assertSame($response->tags[0]->name, 'test php tag'); + $this->assertSame($response->getId(), $pet_id); + $this->assertSame($response->getName(), 'PHP Unit Test'); + $this->assertSame($response->getCategory()->getId(), $pet_id); + $this->assertSame($response->getCategory()->getName(), 'test php category'); + $this->assertSame($response->getTags()[0]->getId(), $pet_id); + $this->assertSame($response->getTags()[0]->getName(), 'test php tag'); } // test getPetByStatus and verify by the "id" of the response public function testFindPetByStatus() { // initialize the API client - $api_client = new Swagger\Client\ApiClient('http://petstore.swagger.io/v2'); + $config = (new Swagger\Client\Configuration())->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); $pet_api = new Swagger\Client\Api\PetAPI($api_client); // return Pet (model) $response = $pet_api->findPetsByStatus("available"); @@ -133,30 +121,32 @@ class PetApiTest extends \PHPUnit_Framework_TestCase public function testUpdatePet() { // initialize the API client - $api_client = new Swagger\Client\ApiClient('http://petstore.swagger.io/v2'); + $config = (new Swagger\Client\Configuration())->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); $pet_id = 10001; // ID of pet that needs to be fetched $pet_api = new Swagger\Client\Api\PetAPI($api_client); // create updated pet object $updated_pet = new Swagger\Client\Model\Pet; - $updated_pet->id = $pet_id; - $updated_pet->name = 'updatePet'; // new name - $updated_pet->status = 'pending'; // new status + $updated_pet->setId($pet_id); + $updated_pet->setName('updatePet'); // new name + $updated_pet->setStatus('pending'); // new status // update Pet (model/json) $update_response = $pet_api->updatePet($updated_pet); // return nothing (void) $this->assertSame($update_response, NULL); // verify updated Pet $response = $pet_api->getPetById($pet_id); - $this->assertSame($response->id, $pet_id); - $this->assertSame($response->status, 'pending'); - $this->assertSame($response->name, 'updatePet'); + $this->assertSame($response->getId(), $pet_id); + $this->assertSame($response->getStatus(), 'pending'); + $this->assertSame($response->getName(), 'updatePet'); } // test updatePet and verify by the "id" of the response public function testUpdatePetWithForm() { // initialize the API client - $api_client = new Swagger\Client\ApiClient('http://petstore.swagger.io/v2'); + $config = (new Swagger\Client\Configuration())->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); $pet_id = 10001; // ID of pet that needs to be fetched $pet_api = new Swagger\Client\Api\PetAPI($api_client); // update Pet (form) @@ -164,20 +154,21 @@ class PetApiTest extends \PHPUnit_Framework_TestCase // return nothing (void) $this->assertSame($update_response, NULL); $response = $pet_api->getPetById($pet_id); - $this->assertSame($response->id, $pet_id); - $this->assertSame($response->name, 'update pet with form'); - $this->assertSame($response->status, 'sold'); + $this->assertSame($response->getId(), $pet_id); + $this->assertSame($response->getName(), 'update pet with form'); + $this->assertSame($response->getStatus(), 'sold'); } // test addPet and verify by the "id" and "name" of the response public function testAddPet() { // initialize the API client - $api_client = new Swagger\Client\ApiClient('http://petstore.swagger.io/v2'); + $config = (new Swagger\Client\Configuration())->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); $new_pet_id = 10001; $new_pet = new Swagger\Client\Model\Pet; - $new_pet->id = $new_pet_id; - $new_pet->name = "PHP Unit Test"; + $new_pet->setId($new_pet_id); + $new_pet->setName("PHP Unit Test"); $pet_api = new Swagger\Client\Api\PetAPI($api_client); // add a new pet (model) $add_response = $pet_api->addPet($new_pet); @@ -185,15 +176,16 @@ class PetApiTest extends \PHPUnit_Framework_TestCase $this->assertSame($add_response, NULL); // verify added Pet $response = $pet_api->getPetById($new_pet_id); - $this->assertSame($response->id, $new_pet_id); - $this->assertSame($response->name, 'PHP Unit Test'); + $this->assertSame($response->getId(), $new_pet_id); + $this->assertSame($response->getName(), 'PHP Unit Test'); } // test upload file public function testUploadFile() { // initialize the API client - $api_client = new Swagger\Client\ApiClient('http://petstore.swagger.io/v2'); + $config = (new Swagger\Client\Configuration())->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); $pet_api = new Swagger\Client\Api\PetAPI($api_client); // upload file $pet_id = 10001; @@ -206,7 +198,9 @@ class PetApiTest extends \PHPUnit_Framework_TestCase public function testGetInventory() { // initialize the API client - $api_client = new Swagger\Client\APIClient('http://petstore.swagger.io/v2'); + $config = new Swagger\Client\Configuration(); + $config->setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\APIClient($config); $store_api = new Swagger\Client\Api\StoreAPI($api_client); // get inventory $get_response = $store_api->getInventory(); diff --git a/samples/client/petstore/php/SwaggerClient-php/tests/StoreApiTest.php b/samples/client/petstore/php/SwaggerClient-php/tests/StoreApiTest.php index a92149fbaf3..05bd873c993 100644 --- a/samples/client/petstore/php/SwaggerClient-php/tests/StoreApiTest.php +++ b/samples/client/petstore/php/SwaggerClient-php/tests/StoreApiTest.php @@ -1,6 +1,6 @@ setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); + $store_api = new Swagger\Client\Api\StoreAPI($api_client); // get inventory $get_response = $store_api->getInventory(); diff --git a/samples/client/petstore/php/SwaggerClient-php/tests/UserApiTest.php b/samples/client/petstore/php/SwaggerClient-php/tests/UserApiTest.php index 181e8a1249e..3efce8b08ba 100644 --- a/samples/client/petstore/php/SwaggerClient-php/tests/UserApiTest.php +++ b/samples/client/petstore/php/SwaggerClient-php/tests/UserApiTest.php @@ -1,6 +1,6 @@ setHost('http://petstore.swagger.io/v2'); + $api_client = new Swagger\Client\ApiClient($config); + $user_api = new Swagger\Client\Api\UserApi($api_client); // login $response = $user_api->loginUser("xxxxx", "yyyyyyyy");