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 41856daa9ba..9402afea736 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 @@ -37,8 +37,7 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { protected boolean supportsAsync = Boolean.TRUE; protected boolean supportsUWP = Boolean.FALSE; protected boolean generatePropertyChanged = Boolean.FALSE; - - + protected Map regexModifiers; protected final Map frameworks; public CSharpClientCodegen() { @@ -124,6 +123,12 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { addSwitch(CodegenConstants.GENERATE_PROPERTY_CHANGED, CodegenConstants.PACKAGE_DESCRIPTION_DESC, this.generatePropertyChanged); + + regexModifiers = new HashMap(); + regexModifiers.put('i', "IgnoreCase"); + regexModifiers.put('m', "Multiline"); + regexModifiers.put('s', "Singleline"); + regexModifiers.put('x', "IgnorePatternWhitespace"); } @Override @@ -350,6 +355,56 @@ public class CSharpClientCodegen extends AbstractCSharpCodegen { return super.postProcessModels(objMap); } + @Override + public void postProcessParameter(CodegenParameter parameter) { + postProcessPattern(parameter.pattern, parameter.vendorExtensions); + super.postProcessParameter(parameter); + } + + @Override + public void postProcessModelProperty(CodegenModel model, CodegenProperty property) { + postProcessPattern(property.pattern, property.vendorExtensions); + super.postProcessModelProperty(model, property); + } + + + /* + * The swagger pattern spec follows the Perl convention and style of modifiers. .NET + * does not support this syntax directly so we need to convert the pattern to a .NET compatible + * format and apply modifiers in a compatible way. + * See https://msdn.microsoft.com/en-us/library/yd1hzczs(v=vs.110).aspx for .NET options. + * See https://github.com/swagger-api/swagger-codegen/pull/2794 for Python's initial implementation from which this is copied. + */ + public void postProcessPattern(String pattern, Map vendorExtensions) { + if(pattern != null) { + int i = pattern.lastIndexOf('/'); + + //Must follow Perl /pattern/modifiers convention + if(pattern.charAt(0) != '/' || i < 2) { + throw new IllegalArgumentException("Pattern must follow the Perl " + + "/pattern/modifiers convention. "+pattern+" is not valid."); + } + + String regex = pattern.substring(1, i).replace("'", "\'"); + List modifiers = new ArrayList(); + + // perl requires an explicit modifier to be culture specific and .NET is the reverse. + modifiers.add("CultureInvariant"); + + for(char c : pattern.substring(i).toCharArray()) { + if(regexModifiers.containsKey(c)) { + String modifier = regexModifiers.get(c); + modifiers.add(modifier); + } else if (c == 'l') { + modifiers.remove("CultureInvariant"); + } + } + + vendorExtensions.put("x-regex", regex); + vendorExtensions.put("x-modifiers", modifiers); + } + } + public void setTargetFramework(String dotnetFramework) { if(!frameworks.containsKey(dotnetFramework)){ LOGGER.warn("Invalid .NET framework version, defaulting to " + this.targetFramework); diff --git a/modules/swagger-codegen/src/main/resources/csharp/Project.mustache b/modules/swagger-codegen/src/main/resources/csharp/Project.mustache index a8f88ea471f..989cedd10ab 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/Project.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/Project.mustache @@ -66,6 +66,7 @@ limitations under the License. + diff --git a/modules/swagger-codegen/src/main/resources/csharp/TestProject.mustache b/modules/swagger-codegen/src/main/resources/csharp/TestProject.mustache index 07448f9cfef..e08b2429864 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/TestProject.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/TestProject.mustache @@ -66,6 +66,7 @@ limitations under the License. + diff --git a/modules/swagger-codegen/src/main/resources/csharp/model.mustache b/modules/swagger-codegen/src/main/resources/csharp/model.mustache index d0fa0a9ff3a..9c9610e5326 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/model.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/model.mustache @@ -3,6 +3,7 @@ using System; using System.Linq; using System.IO; using System.Text; +using System.Text.RegularExpressions; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -13,6 +14,7 @@ using Newtonsoft.Json.Converters; using PropertyChanged; using System.ComponentModel; {{/generatePropertyChanged}} +using System.ComponentModel.DataAnnotations; {{#models}} {{#model}} diff --git a/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache b/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache index 1d3e967b9b0..8f0ec47a1fa 100644 --- a/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache +++ b/modules/swagger-codegen/src/main/resources/csharp/modelGeneric.mustache @@ -5,7 +5,7 @@ {{#generatePropertyChanged}} [ImplementPropertyChanged] {{/generatePropertyChanged}} - public partial class {{classname}} : {{#parent}}{{{parent}}}, {{/parent}} IEquatable<{{classname}}> + public partial class {{classname}} : {{#parent}}{{{parent}}}, {{/parent}} IEquatable<{{classname}}>, IValidatableObject { {{#vars}} {{#isEnum}} @@ -172,8 +172,10 @@ this.{{name}} = {{name}}; return hash; } } - {{#generatePropertyChanged}} + +{{#generatePropertyChanged}} public event PropertyChangedEventHandler PropertyChanged; + public virtual void OnPropertyChanged(string propertyName) { // NOTE: property changed is handled via "code weaving" using Fody. @@ -184,5 +186,41 @@ this.{{name}} = {{name}}; propertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } - {{/generatePropertyChanged}} + +{{/generatePropertyChanged}} + public IEnumerable Validate(ValidationContext validationContext) + { {{#vars}}{{#hasValidation}}{{#maxLength}} + // {{{name}}} ({{{datatype}}}) maxLength + if(this.{{{name}}} != null && this.{{{name}}}.Length > {{maxLength}}) + { + yield return new ValidationResult("Invalid value for {{{name}}}, length must be less than {{maxLength}}.", new [] { "{{{name}}}" }); + } +{{/maxLength}}{{#minLength}} + // {{{name}}} ({{{datatype}}}) minLength + if(this.{{{name}}} != null && this.{{{name}}}.Length < {{minLength}}) + { + yield return new ValidationResult("Invalid value for {{{name}}}, length must be greater than {{minLength}}.", new [] { "{{{name}}}" }); + } +{{/minLength}}{{#maximum}} + // {{{name}}} ({{{datatype}}}) maximum + if(this.{{{name}}} > ({{{datatype}}}){{maximum}}) + { + yield return new ValidationResult("Invalid value for {{{name}}}, must be a value less than or equal to {{maximum}}.", new [] { "{{{name}}}" }); + } +{{/maximum}}{{#minimum}} + // {{{name}}} ({{{datatype}}}) minimum + if(this.{{{name}}} < ({{{datatype}}}){{minimum}}) + { + yield return new ValidationResult("Invalid value for {{{name}}}, must be a value greater than or equal to {{minimum}}.", new [] { "{{{name}}}" }); + } +{{/minimum}}{{#pattern}} + // {{{name}}} ({{{datatype}}}) pattern + Regex regex{{{name}}} = new Regex(@"{{vendorExtensions.x-regex}}"{{#vendorExtensions.x-modifiers}}{{#-first}}, {{/-first}}RegexOptions.{{.}}{{^-last}} | {{/-last}}{{/vendorExtensions.x-modifiers}}); + if (false == regex{{{name}}}.Match(this.{{{name}}}).Success) + { + yield return new ValidationResult("Invalid value for {{{name}}}, must match a pattern of {{pattern}}.", new [] { "{{{name}}}" }); + } +{{/pattern}}{{/hasValidation}}{{/vars}} + yield break; + } }