Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
* 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";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, String> generatorPropertyDefaults = new HashMap<>();

@Override
public Generator opts(ClientOptInput opts) {
Expand All @@ -61,6 +63,38 @@ public Generator opts(ClientOptInput opts) {
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) {
Expand Down Expand Up @@ -88,11 +122,11 @@ private String getHost() {
}

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
Expand All @@ -110,10 +144,10 @@ private void configureGeneratorProperties() {
}
// 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
Expand Down Expand Up @@ -595,7 +629,7 @@ public Reader getTemplate(String name) {
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 {
Expand All @@ -606,13 +640,15 @@ public Reader getTemplate(String name) {
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);
}
}

/*
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -296,6 +297,11 @@ public void processOpts() {
additionalProperties.put(CodegenConstants.INTERFACE_PREFIX, interfacePrefix);
}

@Override
public void postProcessModelProperty(CodegenModel model, CodegenProperty property) {
super.postProcessModelProperty(model, property);
}

@Override
public Map<String, Object> postProcessModels(Map<String, Object> objs) {
List<Object> models = (List<Object>) objs.get("models");
Expand All @@ -315,6 +321,61 @@ public Map<String, Object> postProcessModels(Map<String, Object> objs) {
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<String, Object> postProcessAllModels(Map<String, Object> objs) {
final Map<String, Object> 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<String, Object> models) {
Map<String, CodegenModel> enumRefs = new HashMap<String, CodegenModel>();
for (Map.Entry<String, Object> entry : models.entrySet()) {
CodegenModel model = ModelUtils.getModelByName(entry.getKey(), models);
if (model.isEnum) {
enumRefs.put(entry.getKey(), model);
}
}

for (Map.Entry<String, Object> 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<String, Object> postProcessOperations(Map<String, Object> objs) {
super.postProcessOperations(objs);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -505,11 +505,6 @@ public void setPackageGuid(String packageGuid) {
this.packageGuid = packageGuid;
}

@Override
public Map<String, Object> postProcessModels(Map<String, Object> objMap) {
return super.postProcessModels(objMap);
}

@Override
public void postProcessParameter(CodegenParameter parameter) {
postProcessPattern(parameter.pattern, parameter.vendorExtensions);
Expand All @@ -522,7 +517,6 @@ public void postProcessModelProperty(CodegenModel model, CodegenProperty propert
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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}}
/// <summary>
/// {{^description}}Gets or Sets {{{name}}}{{/description}}{{#description}}{{description}}{{/description}}
Expand All @@ -30,7 +32,7 @@
/// <value>{{description}}</value>
{{/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}}
Expand All @@ -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}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
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;
Expand All @@ -20,18 +21,27 @@ public abstract class AbstractIntegrationTest {

protected abstract Map<String, String> configProperties();

protected Boolean generateSwaggerMetadata = true;

protected Map<String, String> 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<String, String> propertyOverride : systemPropertyOverrides.entrySet()) {
codeGen.setGeneratorPropertyDefault(propertyOverride.getKey(), propertyOverride.getValue());
}

IntegrationTestPathsConfig integrationTestPathsConfig = getIntegrationTestPathsConfig();

String specContent = Files.readFile(integrationTestPathsConfig.getSpecPath().toFile());
Swagger swagger = new SwaggerParser().parse(specContent);

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()
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String, String> builder = new ImmutableMap.Builder<String, String>();
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<String, String> configProperties() {
Map<String, String> 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();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
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;
Expand Down
Loading