diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConstants.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConstants.java index 7a5d41c0dbe..b0b08dfe523 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConstants.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/CodegenConstants.java @@ -4,6 +4,14 @@ package io.swagger.codegen; * A class for storing constants that are used throughout the project. */ public class CodegenConstants { + public static final String APIS = "apis"; + public static final String MODELS = "models"; + public static final String SUPPORTING_FILES = "supportingFiles"; + public static final String MODEL_TESTS = "modelTests"; + public static final String MODEL_DOCS = "modelDocs"; + public static final String API_TESTS = "apiTests"; + public static final String API_DOCS = "apiDocs"; + public static final String API_PACKAGE = "apiPackage"; public static final String API_PACKAGE_DESC = "package for generated api classes"; diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java index 80033e12699..2c166e69577 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/DefaultGenerator.java @@ -33,9 +33,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { private Boolean generateApiDocumentation = null; private Boolean generateModelTests = null; private Boolean generateModelDocumentation = null; + private Boolean generateSwaggerMetadata = true; private String basePath; private String basePathWithoutHost; private String contextPath; + private Map generatorPropertyDefaults = new HashMap<>(); @Override public Generator opts(ClientOptInput opts) { @@ -61,6 +63,38 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { return this; } + /** + * Programmatically disable the output of .swagger-codegen/VERSION, .swagger-codegen-ignore, + * or other metadata files used by Swagger Codegen. + * @param generateSwaggerMetadata true: enable outputs, false: disable outputs + */ + @SuppressWarnings("WeakerAccess") + public void setGenerateSwaggerMetadata(Boolean generateSwaggerMetadata) { + this.generateSwaggerMetadata = generateSwaggerMetadata; + } + + /** + * Set generator properties otherwise pulled from system properties. + * Useful for running tests in parallel without relying on System.properties. + * @param key The system property key + * @param value The system property value + */ + @SuppressWarnings("WeakerAccess") + public void setGeneratorPropertyDefault(final String key, final String value) { + this.generatorPropertyDefaults.put(key, value); + } + + private Boolean getGeneratorPropertyDefaultSwitch(final String key, final Boolean defaultValue) { + String result = null; + if (this.generatorPropertyDefaults.containsKey(key)) { + result = this.generatorPropertyDefaults.get(key); + } + if (result != null) { + return Boolean.valueOf(result); + } + return defaultValue; + } + private String getScheme() { String scheme; if (swagger.getSchemes() != null && swagger.getSchemes().size() > 0) { @@ -88,11 +122,11 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { } private void configureGeneratorProperties() { - // allows generating only models by specifying a CSV of models to generate, or empty for all - generateApis = System.getProperty("apis") != null ? true : null; - generateModels = System.getProperty("models") != null ? true : null; - generateSupportingFiles = System.getProperty("supportingFiles") != null ? true : null; + // NOTE: Boolean.TRUE is required below rather than `true` because of JVM boxing constraints and type inference. + generateApis = System.getProperty(CodegenConstants.APIS) != null ? Boolean.TRUE : getGeneratorPropertyDefaultSwitch(CodegenConstants.APIS, null); + generateModels = System.getProperty(CodegenConstants.MODELS) != null ? Boolean.TRUE : getGeneratorPropertyDefaultSwitch(CodegenConstants.MODELS, null); + generateSupportingFiles = System.getProperty(CodegenConstants.SUPPORTING_FILES) != null ? Boolean.TRUE : getGeneratorPropertyDefaultSwitch(CodegenConstants.SUPPORTING_FILES, null); if (generateApis == null && generateModels == null && generateSupportingFiles == null) { // no specifics are set, generate everything @@ -110,10 +144,10 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { } // model/api tests and documentation options rely on parent generate options (api or model) and no other options. // They default to true in all scenarios and can only be marked false explicitly - generateModelTests = System.getProperty("modelTests") != null ? Boolean.valueOf(System.getProperty("modelTests")) : true; - generateModelDocumentation = System.getProperty("modelDocs") != null ? Boolean.valueOf(System.getProperty("modelDocs")) : true; - generateApiTests = System.getProperty("apiTests") != null ? Boolean.valueOf(System.getProperty("apiTests")) : true; - generateApiDocumentation = System.getProperty("apiDocs") != null ? Boolean.valueOf(System.getProperty("apiDocs")) : true; + generateModelTests = System.getProperty(CodegenConstants.MODEL_TESTS) != null ? Boolean.valueOf(System.getProperty(CodegenConstants.MODEL_TESTS)) : getGeneratorPropertyDefaultSwitch(CodegenConstants.MODEL_TESTS, true); + generateModelDocumentation = System.getProperty(CodegenConstants.MODEL_DOCS) != null ? Boolean.valueOf(System.getProperty(CodegenConstants.MODEL_DOCS)) : getGeneratorPropertyDefaultSwitch(CodegenConstants.MODEL_DOCS, true); + generateApiTests = System.getProperty(CodegenConstants.API_TESTS) != null ? Boolean.valueOf(System.getProperty(CodegenConstants.API_TESTS)) : getGeneratorPropertyDefaultSwitch(CodegenConstants.API_TESTS, true); + generateApiDocumentation = System.getProperty(CodegenConstants.API_DOCS) != null ? Boolean.valueOf(System.getProperty(CodegenConstants.API_DOCS)) : getGeneratorPropertyDefaultSwitch(CodegenConstants.API_DOCS, true); // Additional properties added for tests to exclude references in project related files @@ -595,7 +629,7 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { final String swaggerCodegenIgnore = ".swagger-codegen-ignore"; String ignoreFileNameTarget = config.outputFolder() + File.separator + swaggerCodegenIgnore; File ignoreFile = new File(ignoreFileNameTarget); - if (!ignoreFile.exists()) { + if (generateSwaggerMetadata && !ignoreFile.exists()) { String ignoreFileNameSource = File.separator + config.getCommonTemplateDir() + File.separator + swaggerCodegenIgnore; String ignoreFileContents = readResourceContents(ignoreFileNameSource); try { @@ -606,13 +640,15 @@ public class DefaultGenerator extends AbstractGenerator implements Generator { files.add(ignoreFile); } - final String swaggerVersionMetadata = config.outputFolder() + File.separator + ".swagger-codegen" + File.separator + "VERSION"; - File swaggerVersionMetadataFile = new File(swaggerVersionMetadata); - try { - writeToFile(swaggerVersionMetadata, ImplementationVersion.read()); - files.add(swaggerVersionMetadataFile); - } catch (IOException e) { - throw new RuntimeException("Could not generate supporting file '" + swaggerVersionMetadata + "'", e); + if(generateSwaggerMetadata) { + final String swaggerVersionMetadata = config.outputFolder() + File.separator + ".swagger-codegen" + File.separator + "VERSION"; + File swaggerVersionMetadataFile = new File(swaggerVersionMetadata); + try { + writeToFile(swaggerVersionMetadata, ImplementationVersion.read()); + files.add(swaggerVersionMetadataFile); + } catch (IOException e) { + throw new RuntimeException("Could not generate supporting file '" + swaggerVersionMetadata + "'", e); + } } /* diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractCSharpCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractCSharpCodegen.java index bbd06e02421..243c75d8bd1 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractCSharpCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractCSharpCodegen.java @@ -1,6 +1,7 @@ package io.swagger.codegen.languages; import io.swagger.codegen.*; +import io.swagger.codegen.utils.ModelUtils; import io.swagger.models.properties.*; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; @@ -296,6 +297,11 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co additionalProperties.put(CodegenConstants.INTERFACE_PREFIX, interfacePrefix); } + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + super.postProcessModelProperty(model, property); + } + @Override public Map postProcessModels(Map objs) { List models = (List) objs.get("models"); @@ -315,6 +321,61 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co return postProcessModelsEnum(objs); } + /** + * Invoked by {@link DefaultGenerator} after all models have been post-processed, allowing for a last pass of codegen-specific model cleanup. + * + * @param objs Current state of codegen object model. + * @return An in-place modified state of the codegen object model. + */ + @Override + public Map postProcessAllModels(Map objs) { + final Map processed = super.postProcessAllModels(objs); + postProcessEnumRefs(processed); + return processed; + } + + /** + * C# differs from other languages in that Enums are not _true_ objects; enums are compiled to integral types. + * So, in C#, an enum is considers more like a user-defined primitive. + * + * When working with enums, we can't always assume a RefModel is a nullable type (where default(YourType) == null), + * so this post processing runs through all models to find RefModel'd enums. Then, it runs through all vars and modifies + * those vars referencing RefModel'd enums to work the same as inlined enums rather than as objects. + * @param models + */ + private void postProcessEnumRefs(final Map models) { + Map enumRefs = new HashMap(); + for (Map.Entry entry : models.entrySet()) { + CodegenModel model = ModelUtils.getModelByName(entry.getKey(), models); + if (model.isEnum) { + enumRefs.put(entry.getKey(), model); + } + } + + for (Map.Entry entry : models.entrySet()) { + String swaggerName = entry.getKey(); + CodegenModel model = ModelUtils.getModelByName(swaggerName, models); + if (model != null) { + for (CodegenProperty var : model.allVars) { + if (enumRefs.containsKey(var.datatype)) { + // Handle any enum properties referred to by $ref. + // This is different in C# than most other generators, because enums in C# are compiled to integral types, + // while enums in many other languages are true objects. + CodegenModel refModel = enumRefs.get(var.datatype); + var.allowableValues = refModel.allowableValues; + updateCodegenPropertyEnum(var); + + // We do these after updateCodegenPropertyEnum to avoid generalities that don't mesh with C#. + var.isPrimitiveType = true; + var.isEnum = true; + } + } + } else { + LOGGER.warn("Expected to retrieve model %s by name, but no model was found. Check your -Dmodels inclusions.", swaggerName); + } + } + } + @Override public Map postProcessOperations(Map objs) { super.postProcessOperations(objs); 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 5f739840a2f..eb6e7bc07cc 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 @@ -513,11 +513,6 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { this.packageGuid = packageGuid; } - @Override - public Map postProcessModels(Map objMap) { - return super.postProcessModels(objMap); - } - @Override public void postProcessParameter(CodegenParameter parameter) { postProcessPattern(parameter.pattern, parameter.vendorExtensions); @@ -530,7 +525,6 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { super.postProcessModelProperty(model, property); } - /* * The swagger pattern spec follows the Perl convention and style of modifiers. .NET * does not support this syntax directly so we need to convert the pattern to a .NET compatible diff --git a/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache b/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache index 990818fd328..74d2bddc1e8 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache @@ -12,16 +12,18 @@ {{>visibility}} partial class {{classname}} : {{#parent}}{{{parent}}}, {{/parent}} IEquatable<{{classname}}>{{^netStandard}}{{#validatable}}, IValidatableObject{{/validatable}}{{/netStandard}} { {{#vars}} - {{#isEnum}} -{{>modelInnerEnum}} - {{/isEnum}} {{#items.isEnum}} {{#items}} + {{^complexType}} {{>modelInnerEnum}} + {{/complexType}} {{/items}} {{/items.isEnum}} - {{/vars}} - {{#vars}} + {{#isEnum}} + {{^complexType}} +{{>modelInnerEnum}} + {{/complexType}} + {{/isEnum}} {{#isEnum}} /// /// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}} @@ -30,7 +32,7 @@ /// {{description}} {{/description}} [DataMember(Name="{{baseName}}", EmitDefaultValue={{emitDefaultValue}})] - public {{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}?{{/isContainer}}{{/isEnum}} {{name}} { get; set; } + public {{#complexType}}{{{complexType}}}{{/complexType}}{{^complexType}}{{{datatypeWithEnum}}}{{/complexType}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}} {{name}} { get; set; } {{/isEnum}} {{/vars}} {{#hasRequired}} @@ -53,7 +55,7 @@ {{#hasOnlyReadOnly}} [JsonConstructorAttribute] {{/hasOnlyReadOnly}} - public {{classname}}({{#readWriteVars}}{{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}?{{/isContainer}}{{/isEnum}} {{name}} = {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}default({{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}?{{/isContainer}}{{/isEnum}}){{/defaultValue}}{{^-last}}, {{/-last}}{{/readWriteVars}}){{#parent}} : base({{#parentVars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/parentVars}}){{/parent}} + public {{classname}}({{#readWriteVars}}{{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}}{{/isEnum}} {{name}} = {{#defaultValue}}{{{defaultValue}}}{{/defaultValue}}{{^defaultValue}}default({{{datatypeWithEnum}}}{{#isEnum}}{{^isContainer}}{{^required}}?{{/required}}{{/isContainer}}{{/isEnum}}){{/defaultValue}}{{^-last}}, {{/-last}}{{/readWriteVars}}){{#parent}} : base({{#parentVars}}{{name}}{{#hasMore}}, {{/hasMore}}{{/parentVars}}){{/parent}} { {{#vars}} {{^isInherited}} diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/AbstractIntegrationTest.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/AbstractIntegrationTest.java index e65340b55bf..846ef4446bd 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/AbstractIntegrationTest.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/AbstractIntegrationTest.java @@ -3,6 +3,7 @@ package io.swagger.codegen; import static io.swagger.codegen.testutils.AssertFile.assertPathEqualsRecursively; import java.io.IOException; +import java.util.HashMap; import java.util.Map; import org.testng.annotations.Test; @@ -20,10 +21,19 @@ public abstract class AbstractIntegrationTest { protected abstract Map configProperties(); + protected Boolean generateSwaggerMetadata = true; + + protected Map systemPropertyOverrides = new HashMap<>(); + // @wing328: ignore for the time being until we fix the error with the integration test @Test(enabled = false) public void generatesCorrectDirectoryStructure() throws IOException { DefaultGenerator codeGen = new DefaultGenerator(); + codeGen.setGenerateSwaggerMetadata(generateSwaggerMetadata); + for (Map.Entry propertyOverride : systemPropertyOverrides.entrySet()) { + codeGen.setGeneratorPropertyDefault(propertyOverride.getKey(), propertyOverride.getValue()); + } + IntegrationTestPathsConfig integrationTestPathsConfig = getIntegrationTestPathsConfig(); String specContent = Files.readFile(integrationTestPathsConfig.getSpecPath().toFile()); @@ -31,7 +41,7 @@ public abstract class AbstractIntegrationTest { CodegenConfig codegenConfig = getCodegenConfig(); codegenConfig.setOutputDir(integrationTestPathsConfig.getOutputPath().toString()); - + codegenConfig.setIgnoreFilePathOverride(integrationTestPathsConfig.getIgnoreFilePath().toFile().toString()); ClientOpts clientOpts = new ClientOpts(); clientOpts.setProperties(configProperties()); ClientOptInput opts = new ClientOptInput() diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/csharp/CsharpClientGeneralEnumSupportIntegrationTest.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/csharp/CsharpClientGeneralEnumSupportIntegrationTest.java new file mode 100644 index 00000000000..3dc36696119 --- /dev/null +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/csharp/CsharpClientGeneralEnumSupportIntegrationTest.java @@ -0,0 +1,53 @@ +package io.swagger.codegen.csharp; + +import com.google.common.collect.ImmutableMap; +import io.swagger.codegen.AbstractIntegrationTest; +import io.swagger.codegen.CodegenConfig; +import io.swagger.codegen.CodegenConstants; +import io.swagger.codegen.languages.CSharpClientCodegen; +import io.swagger.codegen.testutils.IntegrationTestPathsConfig; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class CsharpClientGeneralEnumSupportIntegrationTest extends AbstractIntegrationTest { + public CsharpClientGeneralEnumSupportIntegrationTest() { + generateSwaggerMetadata = false; + + ImmutableMap.Builder builder = new ImmutableMap.Builder(); + systemPropertyOverrides = builder + .put(CodegenConstants.APIS, Boolean.FALSE.toString()) + .put(CodegenConstants.MODELS, Boolean.TRUE.toString()) + .put(CodegenConstants.API_DOCS, Boolean.FALSE.toString()) + .put(CodegenConstants.MODEL_DOCS, Boolean.FALSE.toString()) + .put(CodegenConstants.API_TESTS, Boolean.FALSE.toString()) + .put(CodegenConstants.MODEL_TESTS, Boolean.FALSE.toString()) + .put(CodegenConstants.SUPPORTING_FILES, Boolean.FALSE.toString()) + .build(); + } + + @Override + protected IntegrationTestPathsConfig getIntegrationTestPathsConfig() { + return new IntegrationTestPathsConfig("csharp/general/enum-support"); + } + + @Override + protected CodegenConfig getCodegenConfig() { + return new CSharpClientCodegen(); + } + + @Override + protected Map configProperties() { + Map properties = new HashMap<>(); + properties.put(CodegenConstants.EXCLUDE_TESTS, Boolean.TRUE.toString()); + return properties; + } + + // TODO: Remove this when super.generatesCorrectDirectoryStructure() is re-enabled. + @Test(description = "Verify csharp enum support, generalized across supported C# versions.") + public void test() throws IOException { + this.generatesCorrectDirectoryStructure(); + } +} diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/csharp/CsharpModelEnumTest.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/csharp/CsharpModelEnumTest.java index 8a8b0a726b1..ae13bad0b36 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/csharp/CsharpModelEnumTest.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/csharp/CsharpModelEnumTest.java @@ -10,6 +10,7 @@ import io.swagger.models.Model; import io.swagger.models.ModelImpl; import io.swagger.models.RefModel; import io.swagger.models.properties.Property; +import io.swagger.models.properties.RefProperty; import io.swagger.models.properties.StringProperty; import org.testng.Assert; import org.testng.annotations.Test; diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/testutils/IntegrationTestPathsConfig.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/testutils/IntegrationTestPathsConfig.java index 4335c69dd2d..bb08d0bce27 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/testutils/IntegrationTestPathsConfig.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/testutils/IntegrationTestPathsConfig.java @@ -8,15 +8,17 @@ public class IntegrationTestPathsConfig { private final Path outputPath; private final Path specPath; private final Path expectedPath; + private final Path ignoreFilePath; public IntegrationTestPathsConfig(String location) { - this(location + "-spec.json", location + "-result", location + "-expected"); + this(location + "-spec.json", location + "-result", location + "-expected", location + ".ignore"); } - public IntegrationTestPathsConfig(String specLocation, String outputLocation, String expectedLocation) { + public IntegrationTestPathsConfig(String specLocation, String outputLocation, String expectedLocation, String ignoreFileLocation) { outputPath = INTEGRATION_TEST_PATH.resolve(outputLocation); expectedPath = INTEGRATION_TEST_PATH.resolve(expectedLocation); specPath = INTEGRATION_TEST_PATH.resolve(specLocation); + ignoreFilePath = INTEGRATION_TEST_PATH.resolve(ignoreFileLocation); } public Path getOutputPath() { @@ -30,4 +32,6 @@ public class IntegrationTestPathsConfig { public Path getExpectedPath() { return expectedPath; } -} \ No newline at end of file + + public Path getIgnoreFilePath() { return ignoreFilePath; } +} diff --git a/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithInvalidRequiredEnumUsageOnRef.cs b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithInvalidRequiredEnumUsageOnRef.cs new file mode 100644 index 00000000000..2a9a895ecb2 --- /dev/null +++ b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithInvalidRequiredEnumUsageOnRef.cs @@ -0,0 +1,140 @@ +/* + * My title + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * OpenAPI spec version: 1 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.ComponentModel.DataAnnotations; +using SwaggerDateConverter = IO.Swagger.Client.SwaggerDateConverter; + +namespace IO.Swagger.Model +{ + /// + /// Invalid use of required on $ref enum, per Swagger 2.0 spec: Any members other than '$ref' in a JSON Reference object SHALL be ignored. See My_Class_With_Required_Inline_Enum for appropriate usage. + /// + [DataContract] + public partial class MyClassWithInvalidRequiredEnumUsageOnRef : IEquatable, IValidatableObject + { + /// + /// Gets or Sets Days + /// + [DataMember(Name="days", EmitDefaultValue=false)] + public WeekDays? Days { get; set; } + /// + /// Initializes a new instance of the class. + /// + /// First. + /// Days. + public MyClassWithInvalidRequiredEnumUsageOnRef(bool? First = default(bool?), WeekDays? Days = default(WeekDays?)) + { + this.First = First; + this.Days = Days; + } + + /// + /// Gets or Sets First + /// + [DataMember(Name="first", EmitDefaultValue=false)] + public bool? First { get; set; } + + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class MyClassWithInvalidRequiredEnumUsageOnRef {\n"); + sb.Append(" First: ").Append(First).Append("\n"); + sb.Append(" Days: ").Append(Days).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as MyClassWithInvalidRequiredEnumUsageOnRef); + } + + /// + /// Returns true if MyClassWithInvalidRequiredEnumUsageOnRef instances are equal + /// + /// Instance of MyClassWithInvalidRequiredEnumUsageOnRef to be compared + /// Boolean + public bool Equals(MyClassWithInvalidRequiredEnumUsageOnRef input) + { + if (input == null) + return false; + + return + ( + this.First == input.First || + (this.First != null && + this.First.Equals(input.First)) + ) && + ( + this.Days == input.Days || + (this.Days != null && + this.Days.Equals(input.Days)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.First != null) + hashCode = hashCode * 59 + this.First.GetHashCode(); + if (this.Days != null) + hashCode = hashCode * 59 + this.Days.GetHashCode(); + return hashCode; + } + } + + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + yield break; + } + } + +} diff --git a/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithOptionalEnum.cs b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithOptionalEnum.cs new file mode 100644 index 00000000000..870174af6ec --- /dev/null +++ b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithOptionalEnum.cs @@ -0,0 +1,156 @@ +/* + * My title + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * OpenAPI spec version: 1 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.ComponentModel.DataAnnotations; +using SwaggerDateConverter = IO.Swagger.Client.SwaggerDateConverter; + +namespace IO.Swagger.Model +{ + /// + /// MyClassWithOptionalEnum + /// + [DataContract] + public partial class MyClassWithOptionalEnum : IEquatable, IValidatableObject + { + /// + /// Gets or Sets Days + /// + [DataMember(Name="days", EmitDefaultValue=false)] + public WeekDays? Days { get; set; } + /// + /// Initializes a new instance of the class. + /// + /// Quarantine. + /// Grayware. + /// Days. + public MyClassWithOptionalEnum(bool? Quarantine = default(bool?), bool? Grayware = default(bool?), WeekDays? Days = default(WeekDays?)) + { + this.Quarantine = Quarantine; + this.Grayware = Grayware; + this.Days = Days; + } + + /// + /// Gets or Sets Quarantine + /// + [DataMember(Name="quarantine", EmitDefaultValue=false)] + public bool? Quarantine { get; set; } + + /// + /// Gets or Sets Grayware + /// + [DataMember(Name="grayware", EmitDefaultValue=false)] + public bool? Grayware { get; set; } + + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class MyClassWithOptionalEnum {\n"); + sb.Append(" Quarantine: ").Append(Quarantine).Append("\n"); + sb.Append(" Grayware: ").Append(Grayware).Append("\n"); + sb.Append(" Days: ").Append(Days).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as MyClassWithOptionalEnum); + } + + /// + /// Returns true if MyClassWithOptionalEnum instances are equal + /// + /// Instance of MyClassWithOptionalEnum to be compared + /// Boolean + public bool Equals(MyClassWithOptionalEnum input) + { + if (input == null) + return false; + + return + ( + this.Quarantine == input.Quarantine || + (this.Quarantine != null && + this.Quarantine.Equals(input.Quarantine)) + ) && + ( + this.Grayware == input.Grayware || + (this.Grayware != null && + this.Grayware.Equals(input.Grayware)) + ) && + ( + this.Days == input.Days || + (this.Days != null && + this.Days.Equals(input.Days)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Quarantine != null) + hashCode = hashCode * 59 + this.Quarantine.GetHashCode(); + if (this.Grayware != null) + hashCode = hashCode * 59 + this.Grayware.GetHashCode(); + if (this.Days != null) + hashCode = hashCode * 59 + this.Days.GetHashCode(); + return hashCode; + } + } + + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + yield break; + } + } + +} diff --git a/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithOptionalInlineEnum.cs b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithOptionalInlineEnum.cs new file mode 100644 index 00000000000..2146daae4de --- /dev/null +++ b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithOptionalInlineEnum.cs @@ -0,0 +1,206 @@ +/* + * My title + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * OpenAPI spec version: 1 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.ComponentModel.DataAnnotations; +using SwaggerDateConverter = IO.Swagger.Client.SwaggerDateConverter; + +namespace IO.Swagger.Model +{ + /// + /// MyClassWithOptionalInlineEnum + /// + [DataContract] + public partial class MyClassWithOptionalInlineEnum : IEquatable, IValidatableObject + { + /// + /// Gets or Sets Days + /// + [JsonConverter(typeof(StringEnumConverter))] + public enum DaysEnum + { + + /// + /// Enum Sun for "sun" + /// + [EnumMember(Value = "sun")] + Sun, + + /// + /// Enum Mon for "mon" + /// + [EnumMember(Value = "mon")] + Mon, + + /// + /// Enum Tue for "tue" + /// + [EnumMember(Value = "tue")] + Tue, + + /// + /// Enum Wed for "wed" + /// + [EnumMember(Value = "wed")] + Wed, + + /// + /// Enum Thu for "thu" + /// + [EnumMember(Value = "thu")] + Thu, + + /// + /// Enum Fri for "fri" + /// + [EnumMember(Value = "fri")] + Fri, + + /// + /// Enum Sat for "sat" + /// + [EnumMember(Value = "sat")] + Sat + } + + /// + /// Gets or Sets Days + /// + [DataMember(Name="days", EmitDefaultValue=false)] + public DaysEnum? Days { get; set; } + /// + /// Initializes a new instance of the class. + /// + /// Quarantine. + /// Grayware. + /// Days. + public MyClassWithOptionalInlineEnum(bool? Quarantine = default(bool?), bool? Grayware = default(bool?), DaysEnum? Days = default(DaysEnum?)) + { + this.Quarantine = Quarantine; + this.Grayware = Grayware; + this.Days = Days; + } + + /// + /// Gets or Sets Quarantine + /// + [DataMember(Name="quarantine", EmitDefaultValue=false)] + public bool? Quarantine { get; set; } + + /// + /// Gets or Sets Grayware + /// + [DataMember(Name="grayware", EmitDefaultValue=false)] + public bool? Grayware { get; set; } + + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class MyClassWithOptionalInlineEnum {\n"); + sb.Append(" Quarantine: ").Append(Quarantine).Append("\n"); + sb.Append(" Grayware: ").Append(Grayware).Append("\n"); + sb.Append(" Days: ").Append(Days).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as MyClassWithOptionalInlineEnum); + } + + /// + /// Returns true if MyClassWithOptionalInlineEnum instances are equal + /// + /// Instance of MyClassWithOptionalInlineEnum to be compared + /// Boolean + public bool Equals(MyClassWithOptionalInlineEnum input) + { + if (input == null) + return false; + + return + ( + this.Quarantine == input.Quarantine || + (this.Quarantine != null && + this.Quarantine.Equals(input.Quarantine)) + ) && + ( + this.Grayware == input.Grayware || + (this.Grayware != null && + this.Grayware.Equals(input.Grayware)) + ) && + ( + this.Days == input.Days || + (this.Days != null && + this.Days.Equals(input.Days)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Quarantine != null) + hashCode = hashCode * 59 + this.Quarantine.GetHashCode(); + if (this.Grayware != null) + hashCode = hashCode * 59 + this.Grayware.GetHashCode(); + if (this.Days != null) + hashCode = hashCode * 59 + this.Days.GetHashCode(); + return hashCode; + } + } + + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + yield break; + } + } + +} diff --git a/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithRequiredInlineEnum.cs b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithRequiredInlineEnum.cs new file mode 100644 index 00000000000..fb43dccce3f --- /dev/null +++ b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/MyClassWithRequiredInlineEnum.cs @@ -0,0 +1,219 @@ +/* + * My title + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * OpenAPI spec version: 1 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.ComponentModel.DataAnnotations; +using SwaggerDateConverter = IO.Swagger.Client.SwaggerDateConverter; + +namespace IO.Swagger.Model +{ + /// + /// MyClassWithRequiredInlineEnum + /// + [DataContract] + public partial class MyClassWithRequiredInlineEnum : IEquatable, IValidatableObject + { + /// + /// Gets or Sets Days + /// + [JsonConverter(typeof(StringEnumConverter))] + public enum DaysEnum + { + + /// + /// Enum Sun for "sun" + /// + [EnumMember(Value = "sun")] + Sun, + + /// + /// Enum Mon for "mon" + /// + [EnumMember(Value = "mon")] + Mon, + + /// + /// Enum Tue for "tue" + /// + [EnumMember(Value = "tue")] + Tue, + + /// + /// Enum Wed for "wed" + /// + [EnumMember(Value = "wed")] + Wed, + + /// + /// Enum Thu for "thu" + /// + [EnumMember(Value = "thu")] + Thu, + + /// + /// Enum Fri for "fri" + /// + [EnumMember(Value = "fri")] + Fri, + + /// + /// Enum Sat for "sat" + /// + [EnumMember(Value = "sat")] + Sat + } + + /// + /// Gets or Sets Days + /// + [DataMember(Name="days", EmitDefaultValue=false)] + public DaysEnum Days { get; set; } + /// + /// Initializes a new instance of the class. + /// + [JsonConstructorAttribute] + protected MyClassWithRequiredInlineEnum() { } + /// + /// Initializes a new instance of the class. + /// + /// Quarantine. + /// Grayware. + /// Days (required). + public MyClassWithRequiredInlineEnum(bool? Quarantine = default(bool?), bool? Grayware = default(bool?), DaysEnum Days = default(DaysEnum)) + { + // to ensure "Days" is required (not null) + if (Days == null) + { + throw new InvalidDataException("Days is a required property for MyClassWithRequiredInlineEnum and cannot be null"); + } + else + { + this.Days = Days; + } + this.Quarantine = Quarantine; + this.Grayware = Grayware; + } + + /// + /// Gets or Sets Quarantine + /// + [DataMember(Name="quarantine", EmitDefaultValue=false)] + public bool? Quarantine { get; set; } + + /// + /// Gets or Sets Grayware + /// + [DataMember(Name="grayware", EmitDefaultValue=false)] + public bool? Grayware { get; set; } + + + /// + /// Returns the string presentation of the object + /// + /// String presentation of the object + public override string ToString() + { + var sb = new StringBuilder(); + sb.Append("class MyClassWithRequiredInlineEnum {\n"); + sb.Append(" Quarantine: ").Append(Quarantine).Append("\n"); + sb.Append(" Grayware: ").Append(Grayware).Append("\n"); + sb.Append(" Days: ").Append(Days).Append("\n"); + sb.Append("}\n"); + return sb.ToString(); + } + + /// + /// Returns the JSON string presentation of the object + /// + /// JSON string presentation of the object + public string ToJson() + { + return JsonConvert.SerializeObject(this, Formatting.Indented); + } + + /// + /// Returns true if objects are equal + /// + /// Object to be compared + /// Boolean + public override bool Equals(object input) + { + return this.Equals(input as MyClassWithRequiredInlineEnum); + } + + /// + /// Returns true if MyClassWithRequiredInlineEnum instances are equal + /// + /// Instance of MyClassWithRequiredInlineEnum to be compared + /// Boolean + public bool Equals(MyClassWithRequiredInlineEnum input) + { + if (input == null) + return false; + + return + ( + this.Quarantine == input.Quarantine || + (this.Quarantine != null && + this.Quarantine.Equals(input.Quarantine)) + ) && + ( + this.Grayware == input.Grayware || + (this.Grayware != null && + this.Grayware.Equals(input.Grayware)) + ) && + ( + this.Days == input.Days || + (this.Days != null && + this.Days.Equals(input.Days)) + ); + } + + /// + /// Gets the hash code + /// + /// Hash code + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + int hashCode = 41; + if (this.Quarantine != null) + hashCode = hashCode * 59 + this.Quarantine.GetHashCode(); + if (this.Grayware != null) + hashCode = hashCode * 59 + this.Grayware.GetHashCode(); + if (this.Days != null) + hashCode = hashCode * 59 + this.Days.GetHashCode(); + return hashCode; + } + } + + /// + /// To validate all properties of the instance + /// + /// Validation context + /// Validation Result + IEnumerable IValidatableObject.Validate(ValidationContext validationContext) + { + yield break; + } + } + +} diff --git a/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/WeekDays.cs b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/WeekDays.cs new file mode 100644 index 00000000000..ae81432d79b --- /dev/null +++ b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-expected/src/IO.Swagger/Model/WeekDays.cs @@ -0,0 +1,77 @@ +/* + * My title + * + * No description provided (generated by Swagger Codegen https://github.com/swagger-api/swagger-codegen) + * + * OpenAPI spec version: 1 + * + * Generated by: https://github.com/swagger-api/swagger-codegen.git + */ + +using System; +using System.Linq; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Runtime.Serialization; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using System.ComponentModel.DataAnnotations; +using SwaggerDateConverter = IO.Swagger.Client.SwaggerDateConverter; + +namespace IO.Swagger.Model +{ + /// + /// Defines WeekDays + /// + [JsonConverter(typeof(StringEnumConverter))] + public enum WeekDays + { + + /// + /// Enum Sun for "sun" + /// + [EnumMember(Value = "sun")] + Sun, + + /// + /// Enum Mon for "mon" + /// + [EnumMember(Value = "mon")] + Mon, + + /// + /// Enum Tue for "tue" + /// + [EnumMember(Value = "tue")] + Tue, + + /// + /// Enum Wed for "wed" + /// + [EnumMember(Value = "wed")] + Wed, + + /// + /// Enum Thu for "thu" + /// + [EnumMember(Value = "thu")] + Thu, + + /// + /// Enum Fri for "fri" + /// + [EnumMember(Value = "fri")] + Fri, + + /// + /// Enum Sat for "sat" + /// + [EnumMember(Value = "sat")] + Sat + } + +} diff --git a/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-spec.json b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-spec.json new file mode 100644 index 00000000000..99f0dba3974 --- /dev/null +++ b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support-spec.json @@ -0,0 +1,125 @@ +{ + "swagger": "2.0", + "info": { + "version": "1", + "title": "My title" + }, + "host": "localhost:10010", + "basePath": "/", + "schemes": [ + "http", + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": { + "/": { + "get": { + "operationId": "getRoot", + "summary": "Root operation", + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "200 OK Response" + } + } + } + } + }, + "definitions": { + "WeekDays": { + "type": "string", + "enum": [ + "sun", + "mon", + "tue", + "wed", + "thu", + "fri", + "sat" + ] + }, + "My_Class_With_Optional_Enum": { + "properties": { + "quarantine": { + "type": "boolean" + }, + "grayware": { + "type": "boolean" + }, + "days": { + "$ref": "#/definitions/WeekDays" + } + } + }, + + "My_Class_With_Invalid_Required_Enum_Usage_On_Ref": { + "description": "Invalid use of required on $ref enum, per Swagger 2.0 spec: Any members other than '$ref' in a JSON Reference object SHALL be ignored. See My_Class_With_Required_Inline_Enum for appropriate usage.", + "properties": { + "first": { + "type": "boolean" + }, + "days": { + "$ref": "#/definitions/WeekDays", + "required": true + }, + "second": { + "type": "int" + } + } + }, + + "My_Class_With_Optional_Inline_Enum": { + "properties": { + "quarantine": { + "type": "boolean" + }, + "grayware": { + "type": "boolean" + }, + "days": { + "type": "string", + "enum": [ + "sun", + "mon", + "tue", + "wed", + "thu", + "fri", + "sat" + ] + } + } + }, + + "My_Class_With_Required_Inline_Enum": { + "required": [ "days" ], + "properties": { + "quarantine": { + "type": "boolean" + }, + "grayware": { + "type": "boolean" + }, + "days": { + "type": "string", + "enum": [ + "sun", + "mon", + "tue", + "wed", + "thu", + "fri", + "sat" + ] + } + } + } + } +} diff --git a/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support.ignore b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support.ignore new file mode 100644 index 00000000000..48a88a03835 --- /dev/null +++ b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support.ignore @@ -0,0 +1,9 @@ +!**/IO.Swagger/Model/*.cs +**/Api/ +**/Client/ +**/Properties +**/IO.Swagger.Test/ +**/* +*/* +.swagger-codegen/ +*/.* diff --git a/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support.sh b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support.sh new file mode 100755 index 00000000000..896022ab737 --- /dev/null +++ b/modules/swagger-codegen/src/test/resources/integrationtests/csharp/general/enum-support.sh @@ -0,0 +1,14 @@ +#!/usr/bin/env bash + +set -euo pipefail + +declare opts="-DdebugModels -Dproject -Dmodels -DmodelTests=false -DmodelDocs=false $JAVA_OPTS" +declare curdir=$(cd $(dirname "${BASH_SOURCE}") && pwd) + +# NOTE: This is sensitive to the location of this script. +declare clijar=${SWAGGER_CODEGEN_CLI_JAR:-$(cd $curdir && cd ../../../../../../../swagger-codegen-cli/target/ && echo $PWD)/swagger-codegen-cli.jar} + +exec \java ${opts} -jar ${clijar} generate \ + -i enum-support-spec.json -l csharp \ + --additional-properties targetFramework=v4.5 \ + -o enum-support-expected;