From 37d07e1012c303ba74afd101529f1fd9c204c04c Mon Sep 17 00:00:00 2001 From: Jim Schubert Date: Sun, 7 Feb 2016 16:55:08 -0500 Subject: [PATCH] [csharp][aspnet5] AbstractCSharpCodegen base This moves a bit of logic into a base type to prevent lots of duplicates. I've only converted csharp and aspnet5 generators, not csharp 2.0. This base class should provide enough flexibility to support other C# based client and server generators. --- .../languages/AbstractCSharpCodegen.java | 509 ++++++++++++++++ .../languages/AspNet5ServerCodegen.java | 466 ++------------- .../languages/CSharpClientCodegen.java | 563 +++--------------- .../aspnet5/AspNet5ServerOptionsTest.java | 2 - .../IO/Swagger/Properties/AssemblyInfo.cs | 33 + 5 files changed, 674 insertions(+), 899 deletions(-) create mode 100644 modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractCSharpCodegen.java create mode 100644 samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Properties/AssemblyInfo.cs 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 new file mode 100644 index 00000000000..79659d841f5 --- /dev/null +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractCSharpCodegen.java @@ -0,0 +1,509 @@ +package io.swagger.codegen.languages; + +import io.swagger.codegen.*; +import io.swagger.models.properties.*; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.util.*; + +public abstract class AbstractCSharpCodegen extends DefaultCodegen implements CodegenConfig { + + protected boolean optionalAssemblyInfoFlag = true; + protected boolean optionalProjectFileFlag = false; + protected boolean optionalMethodArgumentFlag = true; + protected boolean useDateTimeOffsetFlag = false; + protected boolean useCollection = false; + protected boolean returnICollection = false; + + protected String packageVersion = "1.0.0"; + protected String packageName = "IO.Swagger"; + protected String sourceFolder = "src" + File.separator + packageName; + + protected Set collectionTypes; + protected Set mapTypes; + + protected Logger LOGGER = LoggerFactory.getLogger(AbstractCSharpCodegen.class); + + public AbstractCSharpCodegen() { + super(); + + outputFolder = "generated-code" + File.separator + this.getName(); + embeddedTemplateDir = templateDir = this.getName(); + + collectionTypes = new HashSet( + Arrays.asList( + "IList", "List", + "ICollection", "Collection", + "IEnumerable") + ); + + mapTypes = new HashSet( + Arrays.asList("IDictionary") + ); + + reservedWords = new HashSet( + Arrays.asList( + // local variable names in API methods (endpoints) + "path_", "pathParams", "queryParams", "headerParams", "formParams", "fileParams", + "postBody", "http_header_accepts", "http_header_accept", "apiKeyValue", "response", + "statusCode", + // C# reserved words + "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") + ); + + // TODO: Either include fully qualified names here or handle in DefaultCodegen via lastIndexOf(".") search + languageSpecificPrimitives = new HashSet( + Arrays.asList( + "String", + "string", + "bool?", + "double?", + "int?", + "long?", + "float?", + "byte[]", + "ICollection", + "Collection", + "List", + "Dictionary", + "DateTime?", + "DateTimeOffset?", + "String", + "Boolean", + "Double", + "Int32", + "Int64", + "Float", + "Stream", // not really a primitive, we include it to avoid model import + "Object") + ); + + instantiationTypes.put("array", "List"); + instantiationTypes.put("list", "List"); + instantiationTypes.put("map", "Dictionary"); + + // Nullable types here assume C# 2 support is not part of base + typeMapping = new HashMap(); + typeMapping.put("string", "string"); + typeMapping.put("binary", "byte[]"); + typeMapping.put("boolean", "bool?"); + typeMapping.put("integer", "int?"); + typeMapping.put("float", "float?"); + typeMapping.put("long", "long?"); + typeMapping.put("double", "double?"); + typeMapping.put("number", "double?"); + typeMapping.put("datetime", "DateTime?"); + typeMapping.put("date", "DateTime?"); + typeMapping.put("file", "Stream"); + typeMapping.put("array", "List"); + typeMapping.put("list", "List"); + typeMapping.put("map", "Dictionary"); + typeMapping.put("object", "Object"); + } + + public void setReturnICollection(boolean returnICollection) { + this.returnICollection = returnICollection; + } + + public void setUseCollection(boolean useCollection) { + this.useCollection = useCollection; + if (useCollection) { + typeMapping.put("array", "Collection"); + typeMapping.put("list", "Collection"); + + instantiationTypes.put("array", "Collection"); + instantiationTypes.put("list", "Collection"); + } + } + + public void setOptionalMethodArgumentFlag(boolean flag) { + this.optionalMethodArgumentFlag = flag; + } + + protected void addOption(String key, String description, String defaultValue) { + CliOption option = new CliOption(key, description); + if (defaultValue != null) option.defaultValue(defaultValue); + cliOptions.add(option); + } + + protected void addSwitch(String key, String description, Boolean defaultValue) { + CliOption option = CliOption.newBoolean(key, description); + if (defaultValue != null) option.defaultValue(defaultValue.toString()); + cliOptions.add(option); + } + + public void useDateTimeOffset(boolean flag) { + this.useDateTimeOffsetFlag = flag; + if (flag) typeMapping.put("datetime", "DateTimeOffset?"); + else typeMapping.put("datetime", "DateTime?"); + } + + @Override + public void processOpts() { + super.processOpts(); + + // {{packageVersion}} + if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) { + setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION)); + } else { + additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion); + } + + // {{sourceFolder}} + if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)) { + setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER)); + } else { + additionalProperties.put(CodegenConstants.SOURCE_FOLDER, this.sourceFolder); + } + + // {{packageName}} + if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) { + setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME)); + } else { + additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName); + } + + // {{useDateTimeOffset}} + if (additionalProperties.containsKey(CodegenConstants.USE_DATETIME_OFFSET)) { + useDateTimeOffset(Boolean.valueOf(additionalProperties.get(CodegenConstants.USE_DATETIME_OFFSET).toString())); + } + additionalProperties.put(CodegenConstants.USE_DATETIME_OFFSET, useDateTimeOffsetFlag); + + if (additionalProperties.containsKey(CodegenConstants.USE_COLLECTION)) { + setUseCollection(Boolean.valueOf(additionalProperties.get(CodegenConstants.USE_COLLECTION).toString())); + } + + if (additionalProperties.containsKey(CodegenConstants.RETURN_ICOLLECTION)) { + setReturnICollection(Boolean.valueOf(additionalProperties.get(CodegenConstants.RETURN_ICOLLECTION).toString())); + } + } + + @Override + public Map postProcessModels(Map objs) { + List models = (List) objs.get("models"); + for (Object _mo : models) { + Map mo = (Map) _mo; + CodegenModel cm = (CodegenModel) mo.get("model"); + for (CodegenProperty var : cm.vars) { + // check to see if model name is same as the property name + // which will result in compilation error + // if found, prepend with _ to workaround the limitation + if (var.name.equals(cm.name)) { + var.name = "_" + var.name; + } + } + } + return objs; + } + + @Override + public Map postProcessOperations(Map objs) { + super.postProcessOperations(objs); + if (objs != null) { + Map operations = (Map) objs.get("operations"); + if (operations != null) { + List ops = (List) operations.get("operation"); + for (CodegenOperation operation : ops) { + + // Check return types for collection + if (operation.returnType != null) { + String typeMapping; + int namespaceEnd = operation.returnType.lastIndexOf("."); + if (namespaceEnd > 0) { + typeMapping = operation.returnType.substring(namespaceEnd); + } else { + typeMapping = operation.returnType; + } + + if (this.collectionTypes.contains(typeMapping)) { + operation.isListContainer = true; + operation.returnContainer = operation.returnType; + if (this.returnICollection && ( + typeMapping.startsWith("List") || + typeMapping.startsWith("Collection"))) { + // NOTE: ICollection works for both List and Collection + int genericStart = typeMapping.indexOf("<"); + if (genericStart > 0) { + operation.returnType = "ICollection" + typeMapping.substring(genericStart); + } + } + } else { + operation.returnContainer = operation.returnType; + operation.isMapContainer = this.mapTypes.contains(typeMapping); + } + } + + processOperation(operation); + } + } + } + + return objs; + } + + protected void processOperation(CodegenOperation operation) { + // default noop + } + + @Override + public String apiFileFolder() { + return outputFolder + File.separator + sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar); + } + + @Override + public String modelFileFolder() { + return outputFolder + File.separator + sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar); + } + + @Override + public String toModelFilename(String name) { + // should be the same as the model name + return toModelName(name); + } + + @Override + public String toOperationId(String operationId) { + // throw exception if method name is empty + if (StringUtils.isEmpty(operationId)) { + throw new RuntimeException("Empty method name (operationId) not allowed"); + } + + // 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 camelize(sanitizeName(operationId)); + } + + @Override + public String toVarName(String name) { + // sanitize name + name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. + + // 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); + + // 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) { + // 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(lower) 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 escapeReservedWord(String name) { + return "_" + name; + } + + /** + * Return the example value of the property + * + * @param p Swagger property object + * @return string presentation of the example value of the property + */ + @Override + public String toExampleValue(Property p) { + if (p instanceof StringProperty) { + StringProperty dp = (StringProperty) p; + if (dp.getExample() != null) { + return "\"" + dp.getExample().toString() + "\""; + } + } else if (p instanceof BooleanProperty) { + BooleanProperty dp = (BooleanProperty) p; + if (dp.getExample() != null) { + return dp.getExample().toString(); + } + } else if (p instanceof DateProperty) { + // TODO + } else if (p instanceof DateTimeProperty) { + // TODO + } else if (p instanceof DoubleProperty) { + DoubleProperty dp = (DoubleProperty) p; + if (dp.getExample() != null) { + return dp.getExample().toString(); + } + } else if (p instanceof FloatProperty) { + FloatProperty dp = (FloatProperty) p; + if (dp.getExample() != null) { + return dp.getExample().toString(); + } + } else if (p instanceof IntegerProperty) { + IntegerProperty dp = (IntegerProperty) p; + if (dp.getExample() != null) { + return dp.getExample().toString(); + } + } else if (p instanceof LongProperty) { + LongProperty dp = (LongProperty) p; + if (dp.getExample() != null) { + return dp.getExample().toString(); + } + } + + return null; + } + + /** + * Return the default value of the property + * + * @param p Swagger property object + * @return string presentation of the default value of the property + */ + @Override + public String toDefaultValue(Property p) { + if (p instanceof StringProperty) { + StringProperty dp = (StringProperty) p; + if (dp.getDefault() != null) { + return "\"" + dp.getDefault().toString() + "\""; + } + } else if (p instanceof BooleanProperty) { + BooleanProperty dp = (BooleanProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } else if (p instanceof DateProperty) { + // TODO + } else if (p instanceof DateTimeProperty) { + // TODO + } else if (p instanceof DoubleProperty) { + DoubleProperty dp = (DoubleProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } else if (p instanceof FloatProperty) { + FloatProperty dp = (FloatProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } else if (p instanceof IntegerProperty) { + IntegerProperty dp = (IntegerProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } else if (p instanceof LongProperty) { + LongProperty dp = (LongProperty) p; + if (dp.getDefault() != null) { + return dp.getDefault().toString(); + } + } + + return null; + } + + @Override + public String getSwaggerType(Property p) { + String swaggerType = super.getSwaggerType(p); + String type; + if (typeMapping.containsKey(swaggerType.toLowerCase())) { + type = typeMapping.get(swaggerType.toLowerCase()); + if (languageSpecificPrimitives.contains(type)) { + return type; + } + } else { + type = swaggerType; + } + return toModelName(type); + } + + @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 toModelName(String name) { + name = sanitizeName(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 apiTestFileFolder() { + return outputFolder + ".Test"; + } + + @Override + public String modelTestFileFolder() { + return outputFolder + ".Test"; + } + + @Override + public String toApiTestFilename(String name) { + return toApiName(name) + "Tests"; + } + + @Override + public String toModelTestFilename(String name) { + return toModelName(name) + "Tests"; + } + + + public void setPackageName(String packageName) { + this.packageName = packageName; + } + + public void setPackageVersion(String packageVersion) { + this.packageVersion = packageVersion; + } + + public void setSourceFolder(String sourceFolder) { + this.sourceFolder = sourceFolder; + } +} diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AspNet5ServerCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AspNet5ServerCodegen.java index b6339ee11c6..25290aa5244 100644 --- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AspNet5ServerCodegen.java +++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AspNet5ServerCodegen.java @@ -9,16 +9,7 @@ import org.slf4j.LoggerFactory; import java.io.File; import java.util.*; -public class AspNet5ServerCodegen extends DefaultCodegen implements CodegenConfig { - protected boolean useDateTimeOffsetFlag = false; - protected String packageName = "IO.Swagger"; - protected String packageVersion = "1.0.0"; - protected boolean useCollection = false; - protected boolean returnICollection = false; - protected String sourceFolder = "src" + File.separator + packageName; - - protected Set collectionTypes; - protected Set mapTypes; +public class AspNet5ServerCodegen extends AbstractCSharpCodegen { @SuppressWarnings("hiding") protected Logger LOGGER = LoggerFactory.getLogger(AspNet5ServerCodegen.class); @@ -26,90 +17,21 @@ public class AspNet5ServerCodegen extends DefaultCodegen implements CodegenConfi public AspNet5ServerCodegen() { super(); - outputFolder = "generated-code" + File.separator + "aspnet5"; - embeddedTemplateDir = templateDir = "aspnet5"; + outputFolder = "generated-code" + File.separator + this.getName(); modelTemplateFiles.put("model.mustache", ".cs"); apiTemplateFiles.put("controller.mustache", ".cs"); - // TODO: Create a base C# abstract type to avoid duplication of language functionality - collectionTypes = new HashSet( - Arrays.asList( - "IList", "List", - "ICollection", "Collection", - "IEnumerable") - ); - mapTypes = new HashSet( - Arrays.asList("IDictionary") - ); - - reservedWords = new HashSet( - Arrays.asList( - // local variable names in API methods (endpoints) - "path_", "pathParams", "queryParams", "headerParams", "formParams", "fileParams", - "postBody", "http_header_accepts", "http_header_accept", "apiKeyValue", "response", - "statusCode", - // C# reserved words - "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") - ); - - languageSpecificPrimitives = new HashSet( - Arrays.asList( - "String", - "string", - "bool?", - "double?", - "int?", - "long?", - "float?", - "byte[]", - "ICollection", - "Collection", - "List", - "Dictionary", - "DateTime?", - "DateTimeOffset?", - "String", - "Boolean", - "Double", - "Integer", - "Long", - "Float", - "Stream", // not really a primitive, we include it to avoid model import - "Object") - ); - - instantiationTypes.put("array", "List"); - instantiationTypes.put("list", "List"); - instantiationTypes.put("map", "Dictionary"); - - typeMapping = new HashMap(); - typeMapping.put("string", "string"); - typeMapping.put("binary", "byte[]"); - typeMapping.put("boolean", "bool?"); - typeMapping.put("integer", "int?"); - typeMapping.put("float", "float?"); - typeMapping.put("long", "long?"); - typeMapping.put("double", "double?"); - typeMapping.put("number", "double?"); - typeMapping.put("datetime", "DateTime?"); - typeMapping.put("date", "DateTime?"); - typeMapping.put("file", "Stream"); - typeMapping.put("array", "List"); - typeMapping.put("list", "List"); - typeMapping.put("map", "Dictionary"); - typeMapping.put("object", "Object"); + // contextually reserved words + reservedWords.add("var"); + reservedWords.add("async"); + reservedWords.add("await"); + reservedWords.add("dynamic"); + reservedWords.add("yield"); cliOptions.clear(); + // CLI options addOption(CodegenConstants.PACKAGE_NAME, "C# package name (convention: Title.Case).", this.packageName); @@ -122,82 +44,46 @@ public class AspNet5ServerCodegen extends DefaultCodegen implements CodegenConfi CodegenConstants.SOURCE_FOLDER_DESC, sourceFolder); + // CLI Switches addSwitch(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC, - Boolean.TRUE); - - addSwitch(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, - CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC, - Boolean.TRUE); + this.sortParamsByRequiredFlag); addSwitch(CodegenConstants.USE_DATETIME_OFFSET, CodegenConstants.USE_DATETIME_OFFSET_DESC, - Boolean.FALSE); + this.useDateTimeOffsetFlag); addSwitch(CodegenConstants.USE_COLLECTION, CodegenConstants.USE_COLLECTION_DESC, - Boolean.FALSE); + this.useCollection); addSwitch(CodegenConstants.RETURN_ICOLLECTION, CodegenConstants.RETURN_ICOLLECTION_DESC, - Boolean.FALSE); + this.returnICollection); } - private void addOption(String key, String description, String defaultValue){ - CliOption option = new CliOption(key, description); - if(defaultValue != null) option.defaultValue(defaultValue); - cliOptions.add(option); + @Override + public CodegenType getTag() { + return CodegenType.SERVER; } - private void addSwitch(String key, String description, Boolean defaultValue){ - CliOption option = CliOption.newBoolean(key, description); - if(defaultValue != null) option.defaultValue(defaultValue.toString()); - cliOptions.add(option); + @Override + public String getName() { + return "aspnet5"; + } + + @Override + public String getHelp() { + return "Generates an ASP.NET 5 Web API server."; } @Override public void processOpts() { super.processOpts(); - // {{packageVersion}} - if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) { - setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION)); - } else { - additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion); - } - - // {{sourceFolder}} - if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)){ - setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER)); - } else { - additionalProperties.put(CodegenConstants.SOURCE_FOLDER, this.sourceFolder); - } - - // {{packageName}} - if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) { - setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME)); - } else { - additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName); - } - apiPackage = packageName + ".Controllers"; modelPackage = packageName + ".Models"; - // {{useDateTimeOffset}} - if (additionalProperties.containsKey(CodegenConstants.USE_DATETIME_OFFSET)) - { - useDateTimeOffset(Boolean.valueOf(additionalProperties.get(CodegenConstants.USE_DATETIME_OFFSET).toString())); - } - additionalProperties.put(CodegenConstants.USE_DATETIME_OFFSET, useDateTimeOffsetFlag); - - if (additionalProperties.containsKey(CodegenConstants.USE_COLLECTION)){ - setUseCollection(Boolean.valueOf(additionalProperties.get(CodegenConstants.USE_COLLECTION).toString())); - } - - if (additionalProperties.containsKey(CodegenConstants.RETURN_ICOLLECTION)){ - setReturnICollection(Boolean.valueOf(additionalProperties.get(CodegenConstants.RETURN_ICOLLECTION).toString())); - } - supportingFiles.add(new SupportingFile("global.json", "", "global.json")); supportingFiles.add(new SupportingFile("build.mustache", "", "build.sh")); supportingFiles.add(new SupportingFile("Dockerfile.mustache", this.sourceFolder, "Dockerfile")); @@ -207,43 +93,11 @@ public class AspNet5ServerCodegen extends DefaultCodegen implements CodegenConfi supportingFiles.add(new SupportingFile("project.mustache", this.sourceFolder, "project.json")); supportingFiles.add(new SupportingFile("Startup.mustache", this.sourceFolder, "Startup.cs")); - supportingFiles.add(new SupportingFile("Properties"+File.separator +"launchSettings.json", this.sourceFolder + File.separator + "Properties", "launchSettings.json")); + supportingFiles.add(new SupportingFile("Properties" + File.separator + "launchSettings.json", this.sourceFolder + File.separator + "Properties", "launchSettings.json")); - supportingFiles.add(new SupportingFile("wwwroot" +File.separator + "README.md", this.sourceFolder + File.separator + "wwwroot", "README.md")); - supportingFiles.add(new SupportingFile("wwwroot" +File.separator + "index.html", this.sourceFolder + File.separator + "wwwroot", "index.html")); - supportingFiles.add(new SupportingFile("wwwroot" +File.separator + "web.config", this.sourceFolder + File.separator + "wwwroot", "web.config")); - } - - public void useDateTimeOffset(boolean flag) { - this.useDateTimeOffsetFlag = flag; - if (flag) typeMapping.put("datetime", "DateTimeOffset?"); - else typeMapping.put("datetime", "DateTime?"); - } - - public void setReturnICollection(boolean returnICollection) { - this.returnICollection = returnICollection; - } - - public void setUseCollection(boolean useCollection) { - this.useCollection = useCollection; - if(useCollection){ - typeMapping.put("array", "Collection"); - typeMapping.put("list", "Collection"); - - instantiationTypes.put("array", "Collection"); - instantiationTypes.put("list", "Collection"); - } - } - - @Override - public CodegenType getTag() { return CodegenType.SERVER; } - - @Override - public String getName() { return "aspnet5"; } - - @Override - public String getHelp() { - return "Generates an ASP.NET 5 Web API server."; + supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "README.md", this.sourceFolder + File.separator + "wwwroot", "README.md")); + supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "index.html", this.sourceFolder + File.separator + "wwwroot", "index.html")); + supportingFiles.add(new SupportingFile("wwwroot" + File.separator + "web.config", this.sourceFolder + File.separator + "wwwroot", "web.config")); } @Override @@ -253,263 +107,23 @@ public class AspNet5ServerCodegen extends DefaultCodegen implements CodegenConfi @Override public String modelFileFolder() { - return outputFolder + File.separator + sourceFolder + File.separator + "Models"; + return outputFolder + File.separator + sourceFolder + File.separator + "Models"; } - // TODO: Create a base C# abstract type to avoid duplication of language functionality @Override - public String escapeReservedWord(String name) { - return "_" + name; - } + protected void processOperation(CodegenOperation operation) { + super.processOperation(operation); - // TODO: Create a base C# abstract type to avoid duplication of language functionality - @Override - public String toVarName(String name) { - // sanitize name - name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. - - // 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); - - // for reserved word or word starting with number, append _ - if (reservedWords.contains(name) || name.matches("^\\d.*")) { - name = escapeReservedWord(name); - } - - return name; - } - - // TODO: Create a base C# abstract type to avoid duplication of language functionality - @Override - public String toParamName(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(lower) 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; - } - - // TODO: Create a base C# abstract type to avoid duplication of language functionality - @Override - public String toModelName(String name) { - name = sanitizeName(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); - } - - // TODO: Create a base C# abstract type to avoid duplication of language functionality - @Override - public String toModelFilename(String name) { - // should be the same as the model name - return toModelName(name); - } - - // TODO: Create a base C# abstract type to avoid duplication of language functionality - @Override - public Map postProcessOperations(Map objs) { - super.postProcessOperations(objs); - if(objs != null) { - Map operations = (Map) objs.get("operations"); - if (operations != null) { - List ops = (List) operations.get("operation"); - for (CodegenOperation operation : ops) { - // HACK: Unlikely in the wild, but we need to clean operation paths for MVC Routing - if(operation.path != null){ - String original = operation.path; - operation.path = operation.path.replace("?", "/"); - if(!original.equals(operation.path)){ - LOGGER.warn("Normalized " + original + " to " + operation.path + ". Please verify generated source."); - } - } - - // Check return types for collection - if (operation.returnType != null) { - String typeMapping; - int namespaceEnd = operation.returnType.lastIndexOf("."); - if(namespaceEnd > 0) { - typeMapping = operation.returnType.substring(namespaceEnd); - } else { - typeMapping = operation.returnType; - } - - if(this.collectionTypes.contains(typeMapping)){ - operation.isListContainer = true; - operation.returnContainer = operation.returnType; - if( this.returnICollection && ( - typeMapping.startsWith("List")|| - typeMapping.startsWith("Collection")) ) { - // NOTE: ICollection works for both List and Collection - int genericStart = typeMapping.indexOf("<"); - if(genericStart > 0) { - operation.returnType = "ICollection" + typeMapping.substring(genericStart); - } - } - } else { - operation.returnContainer = operation.returnType; - operation.isMapContainer = this.mapTypes.contains(typeMapping); - } - } - - // Converts, for example, PUT to HttpPut for controller attributes - operation.httpMethod = "Http" + operation.httpMethod.substring(0,1) + operation.httpMethod.substring(1).toLowerCase(); - } + // HACK: Unlikely in the wild, but we need to clean operation paths for MVC Routing + if (operation.path != null) { + String original = operation.path; + operation.path = operation.path.replace("?", "/"); + if (!original.equals(operation.path)) { + LOGGER.warn("Normalized " + original + " to " + operation.path + ". Please verify generated source."); } } - return objs; - } - - // TODO: Create a base C# abstract type to avoid duplication of language functionality - @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); - } - - // TODO: Create a base C# abstract type to avoid duplication of language functionality - @Override - public String getSwaggerType(Property p) { - String swaggerType = super.getSwaggerType(p); - String type = null; - if (typeMapping.containsKey(swaggerType.toLowerCase())) { - type = typeMapping.get(swaggerType.toLowerCase()); - if (languageSpecificPrimitives.contains(type)) { - return type; - } - } else { - type = swaggerType; - } - return toModelName(type); - } - - // TODO: Create a base C# abstract type to avoid duplication of language functionality - @Override - public String toOperationId(String operationId) { - // throw exception if method name is empty - if (StringUtils.isEmpty(operationId)) { - throw new RuntimeException("Empty method name (operationId) not allowed"); - } - - // 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 camelize(sanitizeName(operationId)); - } - - // TODO: Create a base C# abstract type to avoid duplication of language functionality - @Override - public Map postProcessModels(Map objs) { - List models = (List) objs.get("models"); - for (Object _mo : models) { - Map mo = (Map) _mo; - CodegenModel cm = (CodegenModel) mo.get("model"); - for (CodegenProperty var : cm.vars) { - // check to see if model name is same as the property name - // which will result in compilation error - // if found, prepend with _ to workaround the limitation - if (var.name.equals(cm.name)) { - var.name = "_" + var.name; - } - } - } - return objs; - } - - // TODO: Create a base C# abstract type to avoid duplication of language functionality - /** - * Return the default value of the property - * - * @param p Swagger property object - * @return string presentation of the default value of the property - */ - @Override - public String toDefaultValue(Property p) { - if (p instanceof StringProperty) { - StringProperty dp = (StringProperty) p; - if (dp.getDefault() != null) { - return "\"" + dp.getDefault().toString() + "\""; - } - } else if (p instanceof BooleanProperty) { - BooleanProperty dp = (BooleanProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - } else if (p instanceof DateProperty) { - // TODO - } else if (p instanceof DateTimeProperty) { - // TODO - } else if (p instanceof DoubleProperty) { - DoubleProperty dp = (DoubleProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - } else if (p instanceof FloatProperty) { - FloatProperty dp = (FloatProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - } else if (p instanceof IntegerProperty) { - IntegerProperty dp = (IntegerProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - } else if (p instanceof LongProperty) { - LongProperty dp = (LongProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - } - - return null; - } - - - public void setPackageName(String packageName) { - this.packageName = packageName; - } - - public void setPackageVersion(String packageVersion) { - this.packageVersion = packageVersion; - } - - public void setSourceFolder(String sourceFolder) { - this.sourceFolder = sourceFolder; + // Converts, for example, PUT to HttpPut for controller attributes + operation.httpMethod = "Http" + operation.httpMethod.substring(0, 1) + operation.httpMethod.substring(1).toLowerCase(); } } 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 1d6a40831b0..0da5b72f57f 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 @@ -22,159 +22,85 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig { - @SuppressWarnings({ "unused", "hiding" }) +public class CSharpClientCodegen extends AbstractCSharpCodegen { + @SuppressWarnings({"unused", "hiding"}) private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class); - protected boolean optionalAssemblyInfoFlag = true; - protected boolean optionalProjectFileFlag = false; - protected boolean optionalMethodArgumentFlag = true; - protected boolean useDateTimeOffsetFlag = false; - protected boolean useCollection = false; - protected boolean returnICollection = false; + protected String packageGuid = "{" + java.util.UUID.randomUUID().toString().toUpperCase() + "}"; protected String packageTitle = "Swagger Library"; protected String packageProductName = "SwaggerLibrary"; protected String packageDescription = "A library generated from a Swagger doc"; protected String packageCompany = "Swagger"; protected String packageCopyright = "No Copyright"; - 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" + File.separator + "csharp"; modelTemplateFiles.put("model.mustache", ".cs"); apiTemplateFiles.put("api.mustache", ".cs"); - embeddedTemplateDir = templateDir = "csharp"; - apiPackage = "IO.Swagger.Api"; - modelPackage = "IO.Swagger.Model"; modelTestTemplateFiles.put("model_test.mustache", ".cs"); apiTestTemplateFiles.put("api_test.mustache", ".cs"); - reservedWords = new HashSet( - Arrays.asList( - // local variable names in API methods (endpoints) - "path_", "pathParams", "queryParams", "headerParams", "formParams", "fileParams", - "postBody", "http_header_accepts", "http_header_accept", "apiKeyValue", "response", - "statusCode", - // C# reserved words - "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") - ); - - - languageSpecificPrimitives = new HashSet( - Arrays.asList( - "String", - "string", - "bool?", - "double?", - "int?", - "long?", - "float?", - "byte[]", - "ICollection", - "Collection", - "List", - "Dictionary", - "DateTime?", - "DateTimeOffset?", - "String", - "Boolean", - "Double", - "Integer", - "Long", - "Float", - "Stream", // not really a primitive, we include it to avoid model import - "Object") - ); - - instantiationTypes.put("array", "List"); - instantiationTypes.put("list", "List"); - instantiationTypes.put("map", "Dictionary"); - - typeMapping = new HashMap(); - typeMapping.put("string", "string"); - typeMapping.put("binary", "byte[]"); - typeMapping.put("boolean", "bool?"); - typeMapping.put("integer", "int?"); - typeMapping.put("float", "float?"); - typeMapping.put("long", "long?"); - typeMapping.put("double", "double?"); - typeMapping.put("number", "double?"); - typeMapping.put("datetime", "DateTime?"); - typeMapping.put("date", "DateTime?"); - typeMapping.put("file", "Stream"); - typeMapping.put("array", "List"); - typeMapping.put("list", "List"); - typeMapping.put("map", "Dictionary"); - typeMapping.put("object", "Object"); + // C# client default + setSourceFolder("src" + File.separator + "main" + File.separator + "csharp"); cliOptions.clear(); - cliOptions.add(new CliOption(CodegenConstants.PACKAGE_NAME, "C# package name (convention: Camel.Case).") - .defaultValue("IO.Swagger")); - cliOptions.add(new CliOption(CodegenConstants.PACKAGE_VERSION, "C# package version.").defaultValue("1.0.0")); - cliOptions.add(CliOption.newBoolean(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, - CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC).defaultValue(Boolean.TRUE.toString())); - cliOptions.add(CliOption.newBoolean(CodegenConstants.OPTIONAL_METHOD_ARGUMENT, "C# Optional method argument, " + - "e.g. void square(int x=10) (.net 4.0+ only).")); - cliOptions.add(CliOption.newBoolean(CodegenConstants.OPTIONAL_ASSEMBLY_INFO, - CodegenConstants.OPTIONAL_ASSEMBLY_INFO_DESC).defaultValue(Boolean.TRUE.toString())); - cliOptions.add(new CliOption(CodegenConstants.SOURCE_FOLDER, CodegenConstants.SOURCE_FOLDER_DESC).defaultValue(sourceFolder)); - cliOptions.add(CliOption.newBoolean(CodegenConstants.USE_DATETIME_OFFSET, CodegenConstants.USE_DATETIME_OFFSET_DESC)); - cliOptions.add( CliOption.newBoolean(CodegenConstants.USE_COLLECTION, CodegenConstants.USE_COLLECTION_DESC) - .defaultValue(Boolean.FALSE.toString()) ); - cliOptions.add( CliOption.newBoolean(CodegenConstants.RETURN_ICOLLECTION, CodegenConstants.RETURN_ICOLLECTION_DESC) - .defaultValue(Boolean.FALSE.toString()) ); - cliOptions.add(CliOption.newBoolean(CodegenConstants.OPTIONAL_PROJECT_FILE, - CodegenConstants.OPTIONAL_PROJECT_FILE_DESC).defaultValue(Boolean.FALSE.toString())); - cliOptions.add(new CliOption(CodegenConstants.OPTIONAL_PROJECT_GUID, CodegenConstants.OPTIONAL_PROJECT_GUID_DESC)); + // CLI options + addOption(CodegenConstants.PACKAGE_NAME, + "C# package name (convention: Title.Case).", + this.packageName); + + addOption(CodegenConstants.PACKAGE_VERSION, + "C# package version.", + this.packageVersion); + + addOption(CodegenConstants.SOURCE_FOLDER, + CodegenConstants.SOURCE_FOLDER_DESC, + sourceFolder); + + addOption(CodegenConstants.OPTIONAL_PROJECT_GUID, + CodegenConstants.OPTIONAL_PROJECT_GUID_DESC, + null); + + // CLI Switches + addSwitch(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG, + CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC, + this.sortParamsByRequiredFlag); + + addSwitch(CodegenConstants.USE_DATETIME_OFFSET, + CodegenConstants.USE_DATETIME_OFFSET_DESC, + this.useDateTimeOffsetFlag); + + addSwitch(CodegenConstants.USE_COLLECTION, + CodegenConstants.USE_COLLECTION_DESC, + this.useCollection); + + addSwitch(CodegenConstants.RETURN_ICOLLECTION, + CodegenConstants.RETURN_ICOLLECTION_DESC, + this.returnICollection); + + addSwitch(CodegenConstants.OPTIONAL_METHOD_ARGUMENT, + "C# Optional method argument, e.g. void square(int x=10) (.net 4.0+ only).", + this.optionalMethodArgumentFlag); + + addSwitch(CodegenConstants.OPTIONAL_ASSEMBLY_INFO, + CodegenConstants.OPTIONAL_ASSEMBLY_INFO_DESC, + this.optionalAssemblyInfoFlag); + + addSwitch(CodegenConstants.OPTIONAL_PROJECT_FILE, + CodegenConstants.OPTIONAL_PROJECT_FILE_DESC, + this.optionalProjectFileFlag); } @Override public void processOpts() { super.processOpts(); - if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) { - setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION)); - } else { - additionalProperties.put(CodegenConstants.PACKAGE_VERSION, packageVersion); - } - - if (additionalProperties.containsKey(CodegenConstants.SOURCE_FOLDER)){ - setSourceFolder((String) additionalProperties.get(CodegenConstants.SOURCE_FOLDER)); - } - else - { - additionalProperties.put(CodegenConstants.SOURCE_FOLDER, this.sourceFolder); - } - - if (additionalProperties.containsKey(CodegenConstants.PACKAGE_NAME)) { - setPackageName((String) additionalProperties.get(CodegenConstants.PACKAGE_NAME)); - apiPackage = packageName + ".Api"; - modelPackage = packageName + ".Model"; - clientPackage = packageName + ".Client"; - } else { - additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName); - } - - // Use DateTimeOffset - if (additionalProperties.containsKey(CodegenConstants.USE_DATETIME_OFFSET)) - { - useDateTimeOffset(Boolean.valueOf(additionalProperties.get(CodegenConstants.USE_DATETIME_OFFSET).toString())); - } - additionalProperties.put(CodegenConstants.USE_DATETIME_OFFSET, useDateTimeOffsetFlag); + apiPackage = packageName + ".Api"; + modelPackage = packageName + ".Model"; + clientPackage = packageName + ".Client"; additionalProperties.put("clientPackage", clientPackage); @@ -184,51 +110,40 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig additionalProperties.put("packageDescription", packageDescription); additionalProperties.put("packageCompany", packageCompany); additionalProperties.put("packageCopyright", packageCopyright); - - if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_FILE)) - { + + if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_FILE)) { setOptionalProjectFileFlag(Boolean.valueOf( - additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_FILE).toString())); + additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_FILE).toString())); } - - if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_GUID)) - { + + if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_GUID)) { setPackageGuid((String) additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_GUID)); } - additionalProperties.put("packageGuid", packageGuid); - + additionalProperties.put("packageGuid", packageGuid); + if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_METHOD_ARGUMENT)) { setOptionalMethodArgumentFlag(Boolean.valueOf(additionalProperties .get(CodegenConstants.OPTIONAL_METHOD_ARGUMENT).toString())); } additionalProperties.put("optionalMethodArgument", optionalMethodArgumentFlag); - + if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_ASSEMBLY_INFO)) { setOptionalAssemblyInfoFlag(Boolean.valueOf(additionalProperties .get(CodegenConstants.OPTIONAL_ASSEMBLY_INFO).toString())); } - if (additionalProperties.containsKey(CodegenConstants.USE_COLLECTION)){ - setUseCollection(Boolean.valueOf(additionalProperties.get(CodegenConstants.USE_COLLECTION).toString())); - } - - if (additionalProperties.containsKey(CodegenConstants.RETURN_ICOLLECTION)){ - setReturnICollection(Boolean.valueOf(additionalProperties.get(CodegenConstants.RETURN_ICOLLECTION).toString())); - } - - String packageFolder = sourceFolder + File.separator + packageName.replace(".", java.io.File.separator); String clientPackageDir = sourceFolder + File.separator + clientPackage.replace(".", java.io.File.separator); - + //Compute the relative path to the bin directory where the external assemblies live //This is necessary to properly generate the project file int packageDepth = packageFolder.length() - packageFolder.replace(java.io.File.separator, "").length(); String binRelativePath = "..\\"; - for (int i=0; i < packageDepth; i = i+1) + for (int i = 0; i < packageDepth; i = i + 1) binRelativePath += "..\\"; binRelativePath += "bin\\"; additionalProperties.put("binRelativePath", binRelativePath); - + supportingFiles.add(new SupportingFile("Configuration.mustache", clientPackageDir, "Configuration.cs")); supportingFiles.add(new SupportingFile("ApiClient.mustache", @@ -237,7 +152,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig clientPackageDir, "ApiException.cs")); supportingFiles.add(new SupportingFile("ApiResponse.mustache", clientPackageDir, "ApiResponse.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")); @@ -253,6 +168,33 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig } } + @Override + public Map postProcessOperations(Map objs) { + super.postProcessOperations(objs); + if (objs != null) { + Map operations = (Map) objs.get("operations"); + if (operations != null) { + List ops = (List) operations.get("operation"); + for (CodegenOperation operation : ops) { + if (operation.returnType != null) { + operation.returnContainer = operation.returnType; + if (this.returnICollection && ( + operation.returnType.startsWith("List") || + operation.returnType.startsWith("Collection"))) { + // NOTE: ICollection works for both List and Collection + int genericStart = operation.returnType.indexOf("<"); + if (genericStart > 0) { + operation.returnType = "ICollection" + operation.returnType.substring(genericStart); + } + } + } + } + } + } + + return objs; + } + @Override public CodegenType getTag() { return CodegenType.CLIENT; @@ -268,177 +210,6 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig return "Generates a CSharp client library."; } - @Override - public String escapeReservedWord(String name) { - return "_" + name; - } - - @Override - public String apiTestFileFolder() { - return outputFolder + ".Test"; - } - - @Override - public String modelTestFileFolder() { - return outputFolder + ".Test"; - } - - @Override - public String apiFileFolder() { - return outputFolder + File.separator + sourceFolder + File.separator + apiPackage().replace('.', File.separatorChar); - } - - @Override - public String modelFileFolder() { - return outputFolder + File.separator + sourceFolder + File.separator + modelPackage().replace('.', File.separatorChar); - } - - @Override - public String toVarName(String name) { - // sanitize name - name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'. - - // 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); - - // 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) { - // 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(lower) 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 toModelName(String name) { - name = sanitizeName(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 toApiTestFilename(String name) { - return toApiName(name) + "Tests"; - } - - @Override - public String toModelTestFilename(String name) { - return toModelName(name) + "Tests"; - } - - @Override - public Map postProcessOperations(Map objs) { - super.postProcessOperations(objs); - if(objs != null) { - Map operations = (Map) objs.get("operations"); - if (operations != null) { - List ops = (List) operations.get("operation"); - for (CodegenOperation operation : ops) { - if (operation.returnType != null) { - operation.returnContainer = operation.returnType; - if( this.returnICollection && ( - operation.returnType.startsWith("List")|| - operation.returnType.startsWith("Collection")) ) { - // NOTE: ICollection works for both List and Collection - int genericStart = operation.returnType.indexOf("<"); - if(genericStart > 0) { - operation.returnType = "ICollection" + operation.returnType.substring(genericStart); - } - } - } - } - } - } - - return objs; - } - - @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.toLowerCase())) { - type = typeMapping.get(swaggerType.toLowerCase()); - if (languageSpecificPrimitives.contains(type)) { - return type; - } - } else { - type = swaggerType; - } - return toModelName(type); - } - - @Override - public String toOperationId(String operationId) { - // throw exception if method name is empty - if (StringUtils.isEmpty(operationId)) { - throw new RuntimeException("Empty method name (operationId) not allowed"); - } - - // 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 camelize(sanitizeName(operationId)); - } - public void setOptionalAssemblyInfoFlag(boolean flag) { this.optionalAssemblyInfoFlag = flag; } @@ -446,159 +217,9 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig public void setOptionalProjectFileFlag(boolean flag) { this.optionalProjectFileFlag = flag; } - - public void setOptionalMethodArgumentFlag(boolean flag) { - this.optionalMethodArgumentFlag = flag; - } - - public void setReturnICollection(boolean returnICollection) { - this.returnICollection = returnICollection; - } - - public void setUseCollection(boolean useCollection) { - this.useCollection = useCollection; - if(useCollection){ - typeMapping.put("array", "Collection"); - typeMapping.put("list", "Collection"); - - instantiationTypes.put("array", "Collection"); - instantiationTypes.put("list", "Collection"); - } - } - - public void useDateTimeOffset(boolean flag) { - this.useDateTimeOffsetFlag = flag; - if (flag) - typeMapping.put("datetime", "DateTimeOffset?"); - else - typeMapping.put("datetime", "DateTime?"); - } public void setPackageGuid(String packageGuid) { this.packageGuid = packageGuid; } - - public void setPackageName(String packageName) { - this.packageName = packageName; - } - public void setPackageVersion(String packageVersion) { - this.packageVersion = packageVersion; - } - - public void setSourceFolder(String sourceFolder) { - this.sourceFolder = sourceFolder; - } - - @Override - public Map postProcessModels(Map objs) { - List models = (List) objs.get("models"); - for (Object _mo : models) { - Map mo = (Map) _mo; - CodegenModel cm = (CodegenModel) mo.get("model"); - for (CodegenProperty var : cm.vars) { - // check to see if model name is same as the property name - // which will result in compilation error - // if found, prepend with _ to workaround the limitation - if (var.name.equals(cm.name)) { - var.name = "_" + var.name; - } - } - } - return objs; - } - - /** - * Return the default value of the property - * - * @param p Swagger property object - * @return string presentation of the default value of the property - */ - @Override - public String toDefaultValue(Property p) { - if (p instanceof StringProperty) { - StringProperty dp = (StringProperty) p; - if (dp.getDefault() != null) { - return "\"" + dp.getDefault().toString() + "\""; - } - } else if (p instanceof BooleanProperty) { - BooleanProperty dp = (BooleanProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - } else if (p instanceof DateProperty) { - // TODO - } else if (p instanceof DateTimeProperty) { - // TODO - } else if (p instanceof DoubleProperty) { - DoubleProperty dp = (DoubleProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - } else if (p instanceof FloatProperty) { - FloatProperty dp = (FloatProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - } else if (p instanceof IntegerProperty) { - IntegerProperty dp = (IntegerProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - } else if (p instanceof LongProperty) { - LongProperty dp = (LongProperty) p; - if (dp.getDefault() != null) { - return dp.getDefault().toString(); - } - } - - return null; - } - - /** - * Return the example value of the property - * - * @param p Swagger property object - * @return string presentation of the example value of the property - */ - @Override - public String toExampleValue(Property p) { - if (p instanceof StringProperty) { - StringProperty dp = (StringProperty) p; - if (dp.getExample() != null) { - return "\"" + dp.getExample().toString() + "\""; - } - } else if (p instanceof BooleanProperty) { - BooleanProperty dp = (BooleanProperty) p; - if (dp.getExample() != null) { - return dp.getExample().toString(); - } - } else if (p instanceof DateProperty) { - // TODO - } else if (p instanceof DateTimeProperty) { - // TODO - } else if (p instanceof DoubleProperty) { - DoubleProperty dp = (DoubleProperty) p; - if (dp.getExample() != null) { - return dp.getExample().toString(); - } - } else if (p instanceof FloatProperty) { - FloatProperty dp = (FloatProperty) p; - if (dp.getExample() != null) { - return dp.getExample().toString(); - } - } else if (p instanceof IntegerProperty) { - IntegerProperty dp = (IntegerProperty) p; - if (dp.getExample() != null) { - return dp.getExample().toString(); - } - } else if (p instanceof LongProperty) { - LongProperty dp = (LongProperty) p; - if (dp.getExample() != null) { - return dp.getExample().toString(); - } - } - - return null; - } } diff --git a/modules/swagger-codegen/src/test/java/io/swagger/codegen/aspnet5/AspNet5ServerOptionsTest.java b/modules/swagger-codegen/src/test/java/io/swagger/codegen/aspnet5/AspNet5ServerOptionsTest.java index 8c53c8913f3..f42eee01fe0 100644 --- a/modules/swagger-codegen/src/test/java/io/swagger/codegen/aspnet5/AspNet5ServerOptionsTest.java +++ b/modules/swagger-codegen/src/test/java/io/swagger/codegen/aspnet5/AspNet5ServerOptionsTest.java @@ -3,9 +3,7 @@ package io.swagger.codegen.aspnet5; import io.swagger.codegen.AbstractOptionsTest; import io.swagger.codegen.CodegenConfig; import io.swagger.codegen.languages.AspNet5ServerCodegen; -import io.swagger.codegen.languages.CSharpClientCodegen; import io.swagger.codegen.options.AspNet5ServerOptionsProvider; -import io.swagger.codegen.options.CSharpClientOptionsProvider; import mockit.Expectations; import mockit.Tested; diff --git a/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Properties/AssemblyInfo.cs b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..1de9edb2a81 --- /dev/null +++ b/samples/client/petstore/csharp/SwaggerClientTest/Lib/SwaggerClient/src/main/csharp/IO/Swagger/Properties/AssemblyInfo.cs @@ -0,0 +1,33 @@ +using System.Reflection; +using System.Runtime.InteropServices; +using System.Windows; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Swagger Library")] +[assembly: AssemblyDescription("A library generated from a Swagger doc")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Swagger")] +[assembly: AssemblyProduct("SwaggerLibrary")] +[assembly: AssemblyCopyright("No Copyright")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0")] +[assembly: AssemblyFileVersion("1.0.0")]