syntax, String definition) {
+ this.syntax = syntax;
+ this.definition = definition;
+ }
+
+ public abstract Boolean matches(String relativePath);
+
+ public String getDefinition() {
+ return this.definition;
+ }
+
+ protected String getPattern() {
+ if(syntax == null) return this.definition;
+
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < syntax.size(); i++) {
+ Part current = syntax.get(i);
+
+ switch(current.getToken()){
+ case MATCH_ALL:
+ case MATCH_ANY:
+ case ESCAPED_EXCLAMATION:
+ case ESCAPED_SPACE:
+ case PATH_DELIM:
+ case TEXT:
+ case DIRECTORY_MARKER:
+ sb.append(current.getValue());
+ break;
+ case NEGATE:
+ case ROOTED_MARKER:
+ case COMMENT:
+ break;
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Whether or not the rule should be negated. !foo means foo should be removed from previous matches.
+ * Example: **\/*.bak excludes all backup. Adding !/test.bak will include test.bak in the project root.
+ *
+ * NOTE: It is not possible to re-include a file if a parent directory of that file is excluded.
+ */
+ public Boolean getNegated() {
+ return this.syntax != null && this.syntax.size() > 0 && this.syntax.get(0).getToken() == IgnoreLineParser.Token.NEGATE;
+ }
+
+ public Operation evaluate(String relativePath) {
+ if (Boolean.TRUE.equals(matches(relativePath))) {
+ if(Boolean.TRUE.equals(this.getNegated())) {
+ return this.getIncludeOperation();
+ }
+ return this.getExcludeOperation();
+ }
+ return Operation.NOOP;
+ }
+
+ protected Operation getIncludeOperation(){ return Operation.INCLUDE; }
+ protected Operation getExcludeOperation(){ return Operation.EXCLUDE; }
+
+ public static Rule create(String definition) {
+ // NOTE: Comments that start with a : (e.g. //:) are pulled from git documentation for .gitignore
+ // see: https://github.com/git/git/blob/90f7b16b3adc78d4bbabbd426fb69aa78c714f71/Documentation/gitignore.txt
+ Rule rule = null;
+ if (definition.equals(".")) {
+ return new InvalidRule(null, definition, "Pattern '.' is invalid.");
+ } else if (definition.equals("!.")) {
+ return new InvalidRule(null, definition, "Pattern '!.' is invalid.");
+ } else if (definition.startsWith("..")) {
+ return new InvalidRule(null, definition, "Pattern '..' is invalid.");
+ }
+
+ try {
+ List result = IgnoreLineParser.parse(definition);
+
+ Boolean directoryOnly = null;
+ if (result.size() == 0) {
+ return rule;
+ } else if (result.size() == 1) {
+ // single-character filename only
+ Part part = result.get(0);
+ if (IgnoreLineParser.Token.MATCH_ANY.equals(part.getToken())) {
+ rule = new RootedFileRule(result, definition);
+ } else {
+ rule = new FileRule(result, definition);
+ }
+ } else {
+ IgnoreLineParser.Token head = result.get(0).getToken();
+
+ //: An optional prefix "`!`" which negates the pattern; any
+ //: matching file excluded by a previous pattern will become
+ //: included again. It is not possible to re-include a file if a parent
+ //: directory of that file is excluded. Git doesn't list excluded
+ //: directories for performance reasons, so any patterns on contained
+ //: files have no effect, no matter where they are defined.
+ //: Put a backslash ("`\`") in front of the first "`!`" for patterns
+ //: that begin with a literal "`!`", for example, "`\!important!.txt`".
+ // see this.getNegated();
+
+ //: If the pattern ends with a slash, it is removed for the
+ //: purpose of the following description, but it would only find
+ //: a match with a directory. In other words, `foo/` will match a
+ //: directory `foo` and paths underneath it, but will not match a
+ //: regular file or a symbolic link `foo` (this is consistent
+ //: with the way how pathspec works in general in Git).
+ directoryOnly = IgnoreLineParser.Token.DIRECTORY_MARKER.equals(result.get(result.size() - 1).getToken());
+
+ if (directoryOnly) {
+ rule = new DirectoryRule(result, definition);
+ } else if (IgnoreLineParser.Token.PATH_DELIM.equals(head)) {
+ //: A leading slash matches the beginning of the pathname.
+ //: For example, "/{asterisk}.c" matches "cat-file.c" but not
+ //: "mozilla-sha1/sha1.c".
+ rule = new RootedFileRule(result, definition);
+ } else {
+ // case 1
+ //: If the pattern does not contain a slash '/', Git treats it as
+ //: a shell glob pattern and checks for a match against the
+ //: pathname relative to the location of the `.gitignore` file
+ //: (relative to the toplevel of the work tree if not from a
+ //: `.gitignore` file).
+
+ // case 2
+ //: Otherwise, Git treats the pattern as a shell glob suitable
+ //: for consumption by fnmatch(3) with the FNM_PATHNAME flag:
+ //: wildcards in the pattern will not match a / in the pathname.
+ //: For example, "Documentation/{asterisk}.html" matches
+ //: "Documentation/git.html" but not "Documentation/ppc/ppc.html"
+ //: or "tools/perf/Documentation/perf.html".
+
+
+ // case 3
+ //: Two consecutive asterisks ("`**`") in patterns matched against
+ //: full pathname may have special meaning:
+ //:
+ //: - A leading "`**`" followed by a slash means match in all
+ //: directories. For example, "`**/foo`" matches file or directory
+ //: "`foo`" anywhere, the same as pattern "`foo`". "`**/foo/bar`"
+ //: matches file or directory "`bar`" anywhere that is directly
+ //: under directory "`foo`".
+ //:
+ //: - A trailing "`/**`" matches everything inside. For example,
+ //: "`abc/**`" matches all files inside directory "`abc`", relative
+ //: to the location of the `.gitignore` file, with infinite depth.
+ //:
+ //: - A slash followed by two consecutive asterisks then a slash
+ //: matches zero or more directories. For example, "`a/**/b`"
+ //: matches "`a/b`", "`a/x/b`", "`a/x/y/b`" and so on.
+ //:
+ //: - Other consecutive asterisks are considered invalid.
+ rule = new FileRule(result, definition);
+ }
+
+ }
+ } catch (ParserException e) {
+ e.printStackTrace();
+ return new InvalidRule(null, definition, e.getMessage());
+ }
+
+ return rule;
+ }
+}
diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractCSharpCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractCSharpCodegen.java
index db5847d9672..f2db3b5e095 100644
--- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractCSharpCodegen.java
+++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/AbstractCSharpCodegen.java
@@ -2,7 +2,7 @@ package io.swagger.codegen.languages;
import io.swagger.codegen.*;
import io.swagger.models.properties.*;
-import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -12,7 +12,7 @@ import java.util.*;
public abstract class AbstractCSharpCodegen extends DefaultCodegen implements CodegenConfig {
protected boolean optionalAssemblyInfoFlag = true;
- protected boolean optionalProjectFileFlag = false;
+ protected boolean optionalProjectFileFlag = true;
protected boolean optionalEmitDefaultValue = false;
protected boolean optionalMethodArgumentFlag = true;
protected boolean useDateTimeOffsetFlag = false;
@@ -21,7 +21,17 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
protected String packageVersion = "1.0.0";
protected String packageName = "IO.Swagger";
- protected String sourceFolder = "src" + File.separator + packageName;
+ 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 sourceFolder = "src";
+
+ // TODO: Add option for test folder output location. Nice to allow e.g. ./test instead of ./src.
+ // This would require updating relative paths (e.g. path to main project file in test project file)
+ protected String testFolder = sourceFolder;
protected Set collectionTypes;
protected Set mapTypes;
@@ -47,6 +57,10 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
setReservedWordsLowerCase(
Arrays.asList(
+ // set client as a reserved word to avoid conflicts with IO.Swagger.Client
+ // this is a workaround and can be removed if c# api client is updated to use
+ // fully qualified name
+ "client",
// local variable names in API methods (endpoints)
"localVarPath", "localVarPathParams", "localVarQueryParams", "localVarHeaderParams",
"localVarFormParams", "localVarFileParams", "localVarStatusCode", "localVarResponse",
@@ -72,6 +86,7 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
"string",
"bool?",
"double?",
+ "decimal?",
"int?",
"long?",
"float?",
@@ -88,8 +103,8 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
"Int32",
"Int64",
"Float",
- "Guid",
- "Stream", // not really a primitive, we include it to avoid model import
+ "Guid?",
+ "System.IO.Stream", // not really a primitive, we include it to avoid model import
"Object")
);
@@ -101,20 +116,21 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
typeMapping = new HashMap();
typeMapping.put("string", "string");
typeMapping.put("binary", "byte[]");
+ typeMapping.put("bytearray", "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("number", "decimal?");
typeMapping.put("datetime", "DateTime?");
typeMapping.put("date", "DateTime?");
- typeMapping.put("file", "Stream");
+ typeMapping.put("file", "System.IO.Stream");
typeMapping.put("array", "List");
typeMapping.put("list", "List");
typeMapping.put("map", "Dictionary");
typeMapping.put("object", "Object");
- typeMapping.put("uuid", "Guid");
+ typeMapping.put("uuid", "Guid?");
}
public void setReturnICollection(boolean returnICollection) {
@@ -182,7 +198,42 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
} else {
additionalProperties.put(CodegenConstants.PACKAGE_NAME, packageName);
}
+
+ // {{packageTitle}}
+ if (additionalProperties.containsKey(CodegenConstants.PACKAGE_TITLE)) {
+ setPackageTitle((String) additionalProperties.get(CodegenConstants.PACKAGE_TITLE));
+ } else {
+ additionalProperties.put(CodegenConstants.PACKAGE_TITLE, packageTitle);
+ }
+
+ // {{packageProductName}}
+ if (additionalProperties.containsKey(CodegenConstants.PACKAGE_PRODUCTNAME)) {
+ setPackageProductName((String) additionalProperties.get(CodegenConstants.PACKAGE_PRODUCTNAME));
+ } else {
+ additionalProperties.put(CodegenConstants.PACKAGE_PRODUCTNAME, packageProductName);
+ }
+ // {{packageDescription}}
+ if (additionalProperties.containsKey(CodegenConstants.PACKAGE_DESCRIPTION)) {
+ setPackageDescription((String) additionalProperties.get(CodegenConstants.PACKAGE_DESCRIPTION));
+ } else {
+ additionalProperties.put(CodegenConstants.PACKAGE_DESCRIPTION, packageDescription);
+ }
+
+ // {{packageCompany}}
+ if (additionalProperties.containsKey(CodegenConstants.PACKAGE_COMPANY)) {
+ setPackageCompany((String) additionalProperties.get(CodegenConstants.PACKAGE_COMPANY));
+ } else {
+ additionalProperties.put(CodegenConstants.PACKAGE_COMPANY, packageCompany);
+ }
+
+ // {{packageCopyright}}
+ if (additionalProperties.containsKey(CodegenConstants.PACKAGE_COPYRIGHT)) {
+ setPackageCopyright((String) additionalProperties.get(CodegenConstants.PACKAGE_COPYRIGHT));
+ } else {
+ additionalProperties.put(CodegenConstants.PACKAGE_COPYRIGHT, packageCopyright);
+ }
+
// {{useDateTimeOffset}}
if (additionalProperties.containsKey(CodegenConstants.USE_DATETIME_OFFSET)) {
useDateTimeOffset(Boolean.valueOf(additionalProperties.get(CodegenConstants.USE_DATETIME_OFFSET).toString()));
@@ -202,11 +253,6 @@ public abstract class AbstractCSharpCodegen extends DefaultCodegen implements Co
}
}
- @Override
- public String toEnumName(CodegenProperty property) {
- return StringUtils.capitalize(property.name) + "Enum?";
- }
-
@Override
public Map postProcessModels(Map objs) {
List