mirror of
https://github.com/OpenAPITools/openapi-generator.git
synced 2025-07-02 21:50:55 +00:00
Merge pull request #2062 from jimschubert/csharp_common
[csharp][aspnet5] AbstractCSharpCodegen base
This commit is contained in:
commit
e7b18a04d9
@ -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<String> collectionTypes;
|
||||||
|
protected Set<String> 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<String>(
|
||||||
|
Arrays.asList(
|
||||||
|
"IList", "List",
|
||||||
|
"ICollection", "Collection",
|
||||||
|
"IEnumerable")
|
||||||
|
);
|
||||||
|
|
||||||
|
mapTypes = new HashSet<String>(
|
||||||
|
Arrays.asList("IDictionary")
|
||||||
|
);
|
||||||
|
|
||||||
|
reservedWords = new HashSet<String>(
|
||||||
|
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<String>(
|
||||||
|
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<String, String>();
|
||||||
|
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<String, Object> postProcessModels(Map<String, Object> objs) {
|
||||||
|
List<Object> models = (List<Object>) objs.get("models");
|
||||||
|
for (Object _mo : models) {
|
||||||
|
Map<String, Object> mo = (Map<String, Object>) _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<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||||
|
super.postProcessOperations(objs);
|
||||||
|
if (objs != null) {
|
||||||
|
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||||
|
if (operations != null) {
|
||||||
|
List<CodegenOperation> ops = (List<CodegenOperation>) 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<T> and Collection<T>
|
||||||
|
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) + "<string, " + getTypeDeclaration(inner) + ">";
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
@ -9,16 +9,7 @@ import org.slf4j.LoggerFactory;
|
|||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class AspNet5ServerCodegen extends DefaultCodegen implements CodegenConfig {
|
public class AspNet5ServerCodegen extends AbstractCSharpCodegen {
|
||||||
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<String> collectionTypes;
|
|
||||||
protected Set<String> mapTypes;
|
|
||||||
|
|
||||||
@SuppressWarnings("hiding")
|
@SuppressWarnings("hiding")
|
||||||
protected Logger LOGGER = LoggerFactory.getLogger(AspNet5ServerCodegen.class);
|
protected Logger LOGGER = LoggerFactory.getLogger(AspNet5ServerCodegen.class);
|
||||||
@ -26,90 +17,21 @@ public class AspNet5ServerCodegen extends DefaultCodegen implements CodegenConfi
|
|||||||
public AspNet5ServerCodegen() {
|
public AspNet5ServerCodegen() {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
outputFolder = "generated-code" + File.separator + "aspnet5";
|
outputFolder = "generated-code" + File.separator + this.getName();
|
||||||
embeddedTemplateDir = templateDir = "aspnet5";
|
|
||||||
|
|
||||||
modelTemplateFiles.put("model.mustache", ".cs");
|
modelTemplateFiles.put("model.mustache", ".cs");
|
||||||
apiTemplateFiles.put("controller.mustache", ".cs");
|
apiTemplateFiles.put("controller.mustache", ".cs");
|
||||||
|
|
||||||
// TODO: Create a base C# abstract type to avoid duplication of language functionality
|
// contextually reserved words
|
||||||
collectionTypes = new HashSet<String>(
|
reservedWords.add("var");
|
||||||
Arrays.asList(
|
reservedWords.add("async");
|
||||||
"IList", "List",
|
reservedWords.add("await");
|
||||||
"ICollection", "Collection",
|
reservedWords.add("dynamic");
|
||||||
"IEnumerable")
|
reservedWords.add("yield");
|
||||||
);
|
|
||||||
mapTypes = new HashSet<String>(
|
|
||||||
Arrays.asList("IDictionary")
|
|
||||||
);
|
|
||||||
|
|
||||||
reservedWords = new HashSet<String>(
|
|
||||||
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<String>(
|
|
||||||
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<String, String>();
|
|
||||||
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");
|
|
||||||
|
|
||||||
cliOptions.clear();
|
cliOptions.clear();
|
||||||
|
|
||||||
|
// CLI options
|
||||||
addOption(CodegenConstants.PACKAGE_NAME,
|
addOption(CodegenConstants.PACKAGE_NAME,
|
||||||
"C# package name (convention: Title.Case).",
|
"C# package name (convention: Title.Case).",
|
||||||
this.packageName);
|
this.packageName);
|
||||||
@ -122,82 +44,46 @@ public class AspNet5ServerCodegen extends DefaultCodegen implements CodegenConfi
|
|||||||
CodegenConstants.SOURCE_FOLDER_DESC,
|
CodegenConstants.SOURCE_FOLDER_DESC,
|
||||||
sourceFolder);
|
sourceFolder);
|
||||||
|
|
||||||
|
// CLI Switches
|
||||||
addSwitch(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
|
addSwitch(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
|
||||||
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC,
|
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC,
|
||||||
Boolean.TRUE);
|
this.sortParamsByRequiredFlag);
|
||||||
|
|
||||||
addSwitch(CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG,
|
|
||||||
CodegenConstants.SORT_PARAMS_BY_REQUIRED_FLAG_DESC,
|
|
||||||
Boolean.TRUE);
|
|
||||||
|
|
||||||
addSwitch(CodegenConstants.USE_DATETIME_OFFSET,
|
addSwitch(CodegenConstants.USE_DATETIME_OFFSET,
|
||||||
CodegenConstants.USE_DATETIME_OFFSET_DESC,
|
CodegenConstants.USE_DATETIME_OFFSET_DESC,
|
||||||
Boolean.FALSE);
|
this.useDateTimeOffsetFlag);
|
||||||
|
|
||||||
addSwitch(CodegenConstants.USE_COLLECTION,
|
addSwitch(CodegenConstants.USE_COLLECTION,
|
||||||
CodegenConstants.USE_COLLECTION_DESC,
|
CodegenConstants.USE_COLLECTION_DESC,
|
||||||
Boolean.FALSE);
|
this.useCollection);
|
||||||
|
|
||||||
addSwitch(CodegenConstants.RETURN_ICOLLECTION,
|
addSwitch(CodegenConstants.RETURN_ICOLLECTION,
|
||||||
CodegenConstants.RETURN_ICOLLECTION_DESC,
|
CodegenConstants.RETURN_ICOLLECTION_DESC,
|
||||||
Boolean.FALSE);
|
this.returnICollection);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addOption(String key, String description, String defaultValue){
|
@Override
|
||||||
CliOption option = new CliOption(key, description);
|
public CodegenType getTag() {
|
||||||
if(defaultValue != null) option.defaultValue(defaultValue);
|
return CodegenType.SERVER;
|
||||||
cliOptions.add(option);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSwitch(String key, String description, Boolean defaultValue){
|
@Override
|
||||||
CliOption option = CliOption.newBoolean(key, description);
|
public String getName() {
|
||||||
if(defaultValue != null) option.defaultValue(defaultValue.toString());
|
return "aspnet5";
|
||||||
cliOptions.add(option);
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getHelp() {
|
||||||
|
return "Generates an ASP.NET 5 Web API server.";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processOpts() {
|
public void processOpts() {
|
||||||
super.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";
|
apiPackage = packageName + ".Controllers";
|
||||||
modelPackage = packageName + ".Models";
|
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("global.json", "", "global.json"));
|
||||||
supportingFiles.add(new SupportingFile("build.mustache", "", "build.sh"));
|
supportingFiles.add(new SupportingFile("build.mustache", "", "build.sh"));
|
||||||
supportingFiles.add(new SupportingFile("Dockerfile.mustache", this.sourceFolder, "Dockerfile"));
|
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("project.mustache", this.sourceFolder, "project.json"));
|
||||||
supportingFiles.add(new SupportingFile("Startup.mustache", this.sourceFolder, "Startup.cs"));
|
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 + "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 + "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"));
|
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.";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -253,263 +107,23 @@ public class AspNet5ServerCodegen extends DefaultCodegen implements CodegenConfi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String modelFileFolder() {
|
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
|
@Override
|
||||||
public String escapeReservedWord(String name) {
|
protected void processOperation(CodegenOperation operation) {
|
||||||
return "_" + name;
|
super.processOperation(operation);
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Create a base C# abstract type to avoid duplication of language functionality
|
// HACK: Unlikely in the wild, but we need to clean operation paths for MVC Routing
|
||||||
@Override
|
if (operation.path != null) {
|
||||||
public String toVarName(String name) {
|
String original = operation.path;
|
||||||
// sanitize name
|
operation.path = operation.path.replace("?", "/");
|
||||||
name = sanitizeName(name); // FIXME: a parameter should not be assigned. Also declare the methods parameters as 'final'.
|
if (!original.equals(operation.path)) {
|
||||||
|
LOGGER.warn("Normalized " + original + " to " + operation.path + ". Please verify generated source.");
|
||||||
// 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<String, Object> postProcessOperations(Map<String, Object> objs) {
|
|
||||||
super.postProcessOperations(objs);
|
|
||||||
if(objs != null) {
|
|
||||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
|
||||||
if (operations != null) {
|
|
||||||
List<CodegenOperation> ops = (List<CodegenOperation>) 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<T> and Collection<T>
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return objs;
|
// Converts, for example, PUT to HttpPut for controller attributes
|
||||||
}
|
operation.httpMethod = "Http" + operation.httpMethod.substring(0, 1) + operation.httpMethod.substring(1).toLowerCase();
|
||||||
|
|
||||||
// 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) + "<string, " + getTypeDeclaration(inner) + ">";
|
|
||||||
}
|
|
||||||
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<String, Object> postProcessModels(Map<String, Object> objs) {
|
|
||||||
List<Object> models = (List<Object>) objs.get("models");
|
|
||||||
for (Object _mo : models) {
|
|
||||||
Map<String, Object> mo = (Map<String, Object>) _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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,159 +22,85 @@ import org.apache.commons.lang.StringUtils;
|
|||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig {
|
public class CSharpClientCodegen extends AbstractCSharpCodegen {
|
||||||
@SuppressWarnings({ "unused", "hiding" })
|
@SuppressWarnings({"unused", "hiding"})
|
||||||
private static final Logger LOGGER = LoggerFactory.getLogger(CSharpClientCodegen.class);
|
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 packageGuid = "{" + java.util.UUID.randomUUID().toString().toUpperCase() + "}";
|
||||||
protected String packageTitle = "Swagger Library";
|
protected String packageTitle = "Swagger Library";
|
||||||
protected String packageProductName = "SwaggerLibrary";
|
protected String packageProductName = "SwaggerLibrary";
|
||||||
protected String packageDescription = "A library generated from a Swagger doc";
|
protected String packageDescription = "A library generated from a Swagger doc";
|
||||||
protected String packageCompany = "Swagger";
|
protected String packageCompany = "Swagger";
|
||||||
protected String packageCopyright = "No Copyright";
|
protected String packageCopyright = "No Copyright";
|
||||||
protected String packageName = "IO.Swagger";
|
|
||||||
protected String packageVersion = "1.0.0";
|
|
||||||
protected String clientPackage = "IO.Swagger.Client";
|
protected String clientPackage = "IO.Swagger.Client";
|
||||||
protected String sourceFolder = "src" + File.separator + "main" + File.separator + "csharp";
|
|
||||||
|
|
||||||
public CSharpClientCodegen() {
|
public CSharpClientCodegen() {
|
||||||
super();
|
super();
|
||||||
outputFolder = "generated-code" + File.separator + "csharp";
|
|
||||||
modelTemplateFiles.put("model.mustache", ".cs");
|
modelTemplateFiles.put("model.mustache", ".cs");
|
||||||
apiTemplateFiles.put("api.mustache", ".cs");
|
apiTemplateFiles.put("api.mustache", ".cs");
|
||||||
embeddedTemplateDir = templateDir = "csharp";
|
|
||||||
apiPackage = "IO.Swagger.Api";
|
|
||||||
modelPackage = "IO.Swagger.Model";
|
|
||||||
|
|
||||||
modelTestTemplateFiles.put("model_test.mustache", ".cs");
|
modelTestTemplateFiles.put("model_test.mustache", ".cs");
|
||||||
apiTestTemplateFiles.put("api_test.mustache", ".cs");
|
apiTestTemplateFiles.put("api_test.mustache", ".cs");
|
||||||
|
|
||||||
reservedWords = new HashSet<String>(
|
// C# client default
|
||||||
Arrays.asList(
|
setSourceFolder("src" + File.separator + "main" + File.separator + "csharp");
|
||||||
// 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<String>(
|
|
||||||
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<String, String>();
|
|
||||||
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");
|
|
||||||
|
|
||||||
cliOptions.clear();
|
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)
|
// CLI options
|
||||||
.defaultValue(Boolean.FALSE.toString()) );
|
addOption(CodegenConstants.PACKAGE_NAME,
|
||||||
cliOptions.add( CliOption.newBoolean(CodegenConstants.RETURN_ICOLLECTION, CodegenConstants.RETURN_ICOLLECTION_DESC)
|
"C# package name (convention: Title.Case).",
|
||||||
.defaultValue(Boolean.FALSE.toString()) );
|
this.packageName);
|
||||||
cliOptions.add(CliOption.newBoolean(CodegenConstants.OPTIONAL_PROJECT_FILE,
|
|
||||||
CodegenConstants.OPTIONAL_PROJECT_FILE_DESC).defaultValue(Boolean.FALSE.toString()));
|
addOption(CodegenConstants.PACKAGE_VERSION,
|
||||||
cliOptions.add(new CliOption(CodegenConstants.OPTIONAL_PROJECT_GUID, CodegenConstants.OPTIONAL_PROJECT_GUID_DESC));
|
"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
|
@Override
|
||||||
public void processOpts() {
|
public void processOpts() {
|
||||||
super.processOpts();
|
super.processOpts();
|
||||||
|
|
||||||
if (additionalProperties.containsKey(CodegenConstants.PACKAGE_VERSION)) {
|
apiPackage = packageName + ".Api";
|
||||||
setPackageVersion((String) additionalProperties.get(CodegenConstants.PACKAGE_VERSION));
|
modelPackage = packageName + ".Model";
|
||||||
} else {
|
clientPackage = packageName + ".Client";
|
||||||
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);
|
|
||||||
|
|
||||||
additionalProperties.put("clientPackage", clientPackage);
|
additionalProperties.put("clientPackage", clientPackage);
|
||||||
|
|
||||||
@ -184,51 +110,40 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
additionalProperties.put("packageDescription", packageDescription);
|
additionalProperties.put("packageDescription", packageDescription);
|
||||||
additionalProperties.put("packageCompany", packageCompany);
|
additionalProperties.put("packageCompany", packageCompany);
|
||||||
additionalProperties.put("packageCopyright", packageCopyright);
|
additionalProperties.put("packageCopyright", packageCopyright);
|
||||||
|
|
||||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_FILE))
|
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_PROJECT_FILE)) {
|
||||||
{
|
|
||||||
setOptionalProjectFileFlag(Boolean.valueOf(
|
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));
|
setPackageGuid((String) additionalProperties.get(CodegenConstants.OPTIONAL_PROJECT_GUID));
|
||||||
}
|
}
|
||||||
additionalProperties.put("packageGuid", packageGuid);
|
additionalProperties.put("packageGuid", packageGuid);
|
||||||
|
|
||||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_METHOD_ARGUMENT)) {
|
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_METHOD_ARGUMENT)) {
|
||||||
setOptionalMethodArgumentFlag(Boolean.valueOf(additionalProperties
|
setOptionalMethodArgumentFlag(Boolean.valueOf(additionalProperties
|
||||||
.get(CodegenConstants.OPTIONAL_METHOD_ARGUMENT).toString()));
|
.get(CodegenConstants.OPTIONAL_METHOD_ARGUMENT).toString()));
|
||||||
}
|
}
|
||||||
additionalProperties.put("optionalMethodArgument", optionalMethodArgumentFlag);
|
additionalProperties.put("optionalMethodArgument", optionalMethodArgumentFlag);
|
||||||
|
|
||||||
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_ASSEMBLY_INFO)) {
|
if (additionalProperties.containsKey(CodegenConstants.OPTIONAL_ASSEMBLY_INFO)) {
|
||||||
setOptionalAssemblyInfoFlag(Boolean.valueOf(additionalProperties
|
setOptionalAssemblyInfoFlag(Boolean.valueOf(additionalProperties
|
||||||
.get(CodegenConstants.OPTIONAL_ASSEMBLY_INFO).toString()));
|
.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 packageFolder = sourceFolder + File.separator + packageName.replace(".", java.io.File.separator);
|
||||||
String clientPackageDir = sourceFolder + File.separator + clientPackage.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
|
//Compute the relative path to the bin directory where the external assemblies live
|
||||||
//This is necessary to properly generate the project file
|
//This is necessary to properly generate the project file
|
||||||
int packageDepth = packageFolder.length() - packageFolder.replace(java.io.File.separator, "").length();
|
int packageDepth = packageFolder.length() - packageFolder.replace(java.io.File.separator, "").length();
|
||||||
String binRelativePath = "..\\";
|
String binRelativePath = "..\\";
|
||||||
for (int i=0; i < packageDepth; i = i+1)
|
for (int i = 0; i < packageDepth; i = i + 1)
|
||||||
binRelativePath += "..\\";
|
binRelativePath += "..\\";
|
||||||
binRelativePath += "bin\\";
|
binRelativePath += "bin\\";
|
||||||
additionalProperties.put("binRelativePath", binRelativePath);
|
additionalProperties.put("binRelativePath", binRelativePath);
|
||||||
|
|
||||||
supportingFiles.add(new SupportingFile("Configuration.mustache",
|
supportingFiles.add(new SupportingFile("Configuration.mustache",
|
||||||
clientPackageDir, "Configuration.cs"));
|
clientPackageDir, "Configuration.cs"));
|
||||||
supportingFiles.add(new SupportingFile("ApiClient.mustache",
|
supportingFiles.add(new SupportingFile("ApiClient.mustache",
|
||||||
@ -237,7 +152,7 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
clientPackageDir, "ApiException.cs"));
|
clientPackageDir, "ApiException.cs"));
|
||||||
supportingFiles.add(new SupportingFile("ApiResponse.mustache",
|
supportingFiles.add(new SupportingFile("ApiResponse.mustache",
|
||||||
clientPackageDir, "ApiResponse.cs"));
|
clientPackageDir, "ApiResponse.cs"));
|
||||||
|
|
||||||
supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll"));
|
supportingFiles.add(new SupportingFile("Newtonsoft.Json.dll", "bin", "Newtonsoft.Json.dll"));
|
||||||
supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll"));
|
supportingFiles.add(new SupportingFile("RestSharp.dll", "bin", "RestSharp.dll"));
|
||||||
supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat"));
|
supportingFiles.add(new SupportingFile("compile.mustache", "", "compile.bat"));
|
||||||
@ -253,6 +168,33 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, Object> postProcessOperations(Map<String, Object> objs) {
|
||||||
|
super.postProcessOperations(objs);
|
||||||
|
if (objs != null) {
|
||||||
|
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
||||||
|
if (operations != null) {
|
||||||
|
List<CodegenOperation> ops = (List<CodegenOperation>) 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<T> and Collection<T>
|
||||||
|
int genericStart = operation.returnType.indexOf("<");
|
||||||
|
if (genericStart > 0) {
|
||||||
|
operation.returnType = "ICollection" + operation.returnType.substring(genericStart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return objs;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CodegenType getTag() {
|
public CodegenType getTag() {
|
||||||
return CodegenType.CLIENT;
|
return CodegenType.CLIENT;
|
||||||
@ -268,177 +210,6 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
return "Generates a CSharp client library.";
|
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<String, Object> postProcessOperations(Map<String, Object> objs) {
|
|
||||||
super.postProcessOperations(objs);
|
|
||||||
if(objs != null) {
|
|
||||||
Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
|
|
||||||
if (operations != null) {
|
|
||||||
List<CodegenOperation> ops = (List<CodegenOperation>) 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<T> and Collection<T>
|
|
||||||
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) + "<string, " + getTypeDeclaration(inner) + ">";
|
|
||||||
}
|
|
||||||
return super.getTypeDeclaration(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getSwaggerType(Property p) {
|
|
||||||
String swaggerType = super.getSwaggerType(p);
|
|
||||||
String type = null;
|
|
||||||
if (typeMapping.containsKey(swaggerType.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) {
|
public void setOptionalAssemblyInfoFlag(boolean flag) {
|
||||||
this.optionalAssemblyInfoFlag = flag;
|
this.optionalAssemblyInfoFlag = flag;
|
||||||
}
|
}
|
||||||
@ -446,159 +217,9 @@ public class CSharpClientCodegen extends DefaultCodegen implements CodegenConfig
|
|||||||
public void setOptionalProjectFileFlag(boolean flag) {
|
public void setOptionalProjectFileFlag(boolean flag) {
|
||||||
this.optionalProjectFileFlag = 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) {
|
public void setPackageGuid(String packageGuid) {
|
||||||
this.packageGuid = 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<String, Object> postProcessModels(Map<String, Object> objs) {
|
|
||||||
List<Object> models = (List<Object>) objs.get("models");
|
|
||||||
for (Object _mo : models) {
|
|
||||||
Map<String, Object> mo = (Map<String, Object>) _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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,7 @@ package io.swagger.codegen.aspnet5;
|
|||||||
import io.swagger.codegen.AbstractOptionsTest;
|
import io.swagger.codegen.AbstractOptionsTest;
|
||||||
import io.swagger.codegen.CodegenConfig;
|
import io.swagger.codegen.CodegenConfig;
|
||||||
import io.swagger.codegen.languages.AspNet5ServerCodegen;
|
import io.swagger.codegen.languages.AspNet5ServerCodegen;
|
||||||
import io.swagger.codegen.languages.CSharpClientCodegen;
|
|
||||||
import io.swagger.codegen.options.AspNet5ServerOptionsProvider;
|
import io.swagger.codegen.options.AspNet5ServerOptionsProvider;
|
||||||
import io.swagger.codegen.options.CSharpClientOptionsProvider;
|
|
||||||
import mockit.Expectations;
|
import mockit.Expectations;
|
||||||
import mockit.Tested;
|
import mockit.Tested;
|
||||||
|
|
||||||
|
@ -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")]
|
Loading…
x
Reference in New Issue
Block a user