From 53009ec19492e77ff5fb5cbf2b261d9c491b0423 Mon Sep 17 00:00:00 2001
From: "P.Y. Laligand" <py.laligand@gmail.com>
Date: Mon, 18 Sep 2017 20:41:41 -0700
Subject: [PATCH] Added support for enums in Dart.

---
 .../codegen/languages/DartClientCodegen.java  | 62 ++++++++++++++++++-
 .../main/resources/dart/api_client.mustache   | 14 ++++-
 .../src/main/resources/dart/apilib.mustache   |  2 +-
 .../src/main/resources/dart/class.mustache    | 14 +++++
 .../src/main/resources/dart/enum.mustache     | 26 ++++++++
 .../src/main/resources/dart/model.mustache    | 22 ++-----
 .../dart/swagger/.swagger-codegen/VERSION     |  2 +-
 .../petstore/dart/swagger/docs/StoreApi.md    |  2 +-
 .../client/petstore/dart/swagger/lib/api.dart |  2 +-
 .../petstore/dart/swagger/lib/api_client.dart |  6 +-
 .../dart/swagger/lib/model/api_response.dart  |  2 -
 .../dart/swagger/lib/model/category.dart      |  2 -
 .../dart/swagger/lib/model/order.dart         |  2 -
 .../petstore/dart/swagger/lib/model/pet.dart  |  2 -
 .../petstore/dart/swagger/lib/model/tag.dart  |  2 -
 .../petstore/dart/swagger/lib/model/user.dart |  2 -
 16 files changed, 124 insertions(+), 40 deletions(-)
 create mode 100644 modules/swagger-codegen/src/main/resources/dart/class.mustache
 create mode 100644 modules/swagger-codegen/src/main/resources/dart/enum.mustache

diff --git a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/DartClientCodegen.java b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/DartClientCodegen.java
index da10196bfda6..b2321f0b3675 100644
--- a/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/DartClientCodegen.java
+++ b/modules/swagger-codegen/src/main/java/io/swagger/codegen/languages/DartClientCodegen.java
@@ -3,17 +3,23 @@
 import io.swagger.codegen.CliOption;
 import io.swagger.codegen.CodegenConfig;
 import io.swagger.codegen.CodegenConstants;
+import io.swagger.codegen.CodegenModel;
+import io.swagger.codegen.CodegenProperty;
 import io.swagger.codegen.CodegenType;
 import io.swagger.codegen.DefaultCodegen;
 import io.swagger.codegen.SupportingFile;
+import io.swagger.models.Model;
 import io.swagger.models.properties.ArrayProperty;
 import io.swagger.models.properties.MapProperty;
 import io.swagger.models.properties.Property;
 
 import java.io.File;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 public class DartClientCodegen extends DefaultCodegen implements CodegenConfig {
     public static final String BROWSER_CLIENT = "browserClient";
@@ -182,7 +188,7 @@ public void processOpts() {
 
 
     @Override
-    public String escapeReservedWord(String name) {           
+    public String escapeReservedWord(String name) {
         if(this.reservedWordsMappings().containsKey(name)) {
             return this.reservedWordsMappings().get(name);
         }
@@ -300,6 +306,60 @@ public String getSwaggerType(Property p) {
         return toModelName(type);
     }
 
+    @Override
+    public Map<String, Object> postProcessModels(Map<String, Object> objs) {
+        Map<String, Object> result = postProcessModelsEnum(objs);
+
+        // Build a list of all the enum models.
+        List<Object> models = (List<Object>) objs.get("models");
+        // Check if there already exists a list.
+        Object storedTransformers = additionalProperties.get("transformers");
+        List<Map<String, String>> enumTransformers = storedTransformers != null ?
+                (List<Map<String, String>>) storedTransformers :
+                new ArrayList<Map<String, String>>();
+        for (Object modelObject : models) {
+            Map<String, Object> modelMap = (Map<String, Object>) modelObject;
+            CodegenModel model = (CodegenModel) modelMap.get("model");
+            if (model.isEnum && model.allowableValues != null) {
+                Map<String, String> enumObject = new HashMap<String, String>();
+                String className = model.classname;
+                enumObject.put("className", className);
+                enumObject.put("transformer", className + "TypeTransformer");
+                enumTransformers.add(enumObject);
+            }
+        }
+        // Store the list as an additional property.
+        additionalProperties.put("transformers", enumTransformers);
+        return result;
+    }
+
+    @Override
+    public String toEnumVarName(String value, String datatype) {
+        if (value.length() == 0) {
+            return "EMPTY";
+        }
+
+        // The lone difference with the super version is the replacement of non
+        // word characters with '__' instead of '_'. This is to handle negative
+        // numbers, so that e.g. -1 is transformed into '__1' and not '_1' like
+        // 1 is.
+        String var = value.replaceAll("\\W+", "__").toUpperCase();
+        if (var.matches("\\d.*")) {
+            return "_" + var;
+        } else {
+            return var;
+        }
+    }
+
+    @Override
+    public String toEnumValue(String value, String datatype) {
+      if ("number".equalsIgnoreCase(datatype) || "int".equalsIgnoreCase(datatype)) {
+          return value;
+      } else {
+          return "\"" + escapeText(value) + "\"";
+      }
+    }
+
     @Override
     public String toOperationId(String operationId) {
         // method name cannot use reserved keyword, e.g. return
diff --git a/modules/swagger-codegen/src/main/resources/dart/api_client.mustache b/modules/swagger-codegen/src/main/resources/dart/api_client.mustache
index 86e698eb836e..d0665ff05931 100644
--- a/modules/swagger-codegen/src/main/resources/dart/api_client.mustache
+++ b/modules/swagger-codegen/src/main/resources/dart/api_client.mustache
@@ -16,7 +16,8 @@ class ApiClient {
   Map<String, Authentication> _authentications = {};
 
   final dson = new Dartson.JSON()
-                   ..addTransformer(new DateTimeParser(), DateTime);
+      {{#transformers}}..addTransformer(new {{transformer}}(), {{className}})
+      {{/transformers}}..addTransformer(new DateTimeParser(), DateTime);
 
   final _RegList = new RegExp(r'^List<(.*)>$');
   final _RegMap = new RegExp(r'^Map<String,(.*)>$');
@@ -46,7 +47,14 @@ class ApiClient {
         {{#models}}
           {{#model}}
         case '{{classname}}':
+            {{#isEnum}}
+          final listValue = [value];
+          final List<dynamic> listResult = dson.map(listValue, []);
+          return listResult[0];
+            {{/isEnum}}
+            {{^isEnum}}
           return dson.map(value, new {{classname}}());
+            {{/isEnum}}
           {{/model}}
         {{/models}}
         default:
@@ -116,7 +124,7 @@ class ApiClient {
     headerParams['Content-Type'] = contentType;
 
     if(body is MultipartRequest) {
-      var request = new MultipartRequest(method, Uri.parse(url));      
+      var request = new MultipartRequest(method, Uri.parse(url));
       request.fields.addAll(body.fields);
       request.files.addAll(body.files);
       request.headers.addAll(body.headers);
@@ -141,7 +149,7 @@ class ApiClient {
   }
 
   /// Update query and header parameters based on authentication settings.
-  /// @param authNames The authentications to apply  
+  /// @param authNames The authentications to apply
   void _updateParamsForAuth(List<String> authNames, List<QueryParam> queryParams, Map<String, String> headerParams) {
     authNames.forEach((authName) {
       Authentication auth = _authentications[authName];
diff --git a/modules/swagger-codegen/src/main/resources/dart/apilib.mustache b/modules/swagger-codegen/src/main/resources/dart/apilib.mustache
index 8f131054f25b..8782ce2236d8 100644
--- a/modules/swagger-codegen/src/main/resources/dart/apilib.mustache
+++ b/modules/swagger-codegen/src/main/resources/dart/apilib.mustache
@@ -6,6 +6,7 @@ import 'package:http/browser_client.dart';{{/browserClient}}
 import 'package:http/http.dart';
 import 'package:dartson/dartson.dart';
 import 'package:dartson/transformers/date_time.dart';
+import 'package:dartson/type_transformer.dart';
 
 part 'api_client.dart';
 part 'api_helper.dart';
@@ -21,4 +22,3 @@ part 'auth/http_basic_auth.dart';
 {{/model}}{{/models}}
 
 ApiClient defaultApiClient = new ApiClient();
-
diff --git a/modules/swagger-codegen/src/main/resources/dart/class.mustache b/modules/swagger-codegen/src/main/resources/dart/class.mustache
new file mode 100644
index 000000000000..d92258c484fa
--- /dev/null
+++ b/modules/swagger-codegen/src/main/resources/dart/class.mustache
@@ -0,0 +1,14 @@
+@Entity()
+class {{classname}} {
+  {{#vars}}{{#description}}/* {{{description}}} */{{/description}}
+  @Property(name: '{{baseName}}')
+  {{{datatype}}} {{name}} = {{{defaultValue}}};
+  {{#allowableValues}}{{#min}} // range from {{min}} to {{max}}{{/min}}//{{^min}}enum {{name}}Enum { {{#values}} {{.}}, {{/values}} };{{/min}}{{/allowableValues}}
+  {{/vars}}
+  {{classname}}();
+
+  @override
+  String toString()  {
+    return '{{classname}}[{{#vars}}{{name}}=${{name}}, {{/vars}}]';
+  }
+}
diff --git a/modules/swagger-codegen/src/main/resources/dart/enum.mustache b/modules/swagger-codegen/src/main/resources/dart/enum.mustache
new file mode 100644
index 000000000000..7270f80a71a4
--- /dev/null
+++ b/modules/swagger-codegen/src/main/resources/dart/enum.mustache
@@ -0,0 +1,26 @@
+@Entity()
+enum {{classname}} {
+  {{#allowableValues}}{{#enumVars}}{{name}}{{^-last}},{{/-last}}
+  {{/enumVars}}{{/allowableValues}}
+}
+
+class {{classname}}TypeTransformer extends TypeTransformer<{{classname}}> {
+
+  @override
+  dynamic encode({{classname}} data) {
+    switch(data) {
+      {{#allowableValues}}{{#enumVars}}case {{classname}}.{{name}}: return {{value}};
+      {{/enumVars}}{{/allowableValues}}
+      default: throw('Unknown enum value to encode: $data');
+    }
+  }
+
+  @override
+  {{classname}} decode(dynamic data) {
+    switch (data) {
+      {{#allowableValues}}{{#enumVars}}case {{value}}: return {{classname}}.{{name}};
+      {{/enumVars}}{{/allowableValues}}
+      default: throw('Unknown enum value to decode: $data');
+    }
+  }
+}
diff --git a/modules/swagger-codegen/src/main/resources/dart/model.mustache b/modules/swagger-codegen/src/main/resources/dart/model.mustache
index 5fe107c7849a..1fa14e179a79 100644
--- a/modules/swagger-codegen/src/main/resources/dart/model.mustache
+++ b/modules/swagger-codegen/src/main/resources/dart/model.mustache
@@ -1,19 +1,7 @@
 part of {{pubName}}.api;
 
-{{#models}}{{#model}}
-@Entity()
-class {{classname}} {
-  {{#vars}}{{#description}}/* {{{description}}} */{{/description}}
-  @Property(name: '{{baseName}}')
-  {{{datatype}}} {{name}} = {{{defaultValue}}};
-  {{#allowableValues}}{{#min}} // range from {{min}} to {{max}}{{/min}}//{{^min}}enum {{name}}Enum { {{#values}} {{.}}, {{/values}} };{{/min}}{{/allowableValues}}
-  {{/vars}}
-  {{classname}}();
-
-  @override
-  String toString()  {
-    return '{{classname}}[{{#vars}}{{name}}=${{name}}, {{/vars}}]';
-  }
-
-}
-{{/model}}{{/models}}
+{{#models}}
+{{#model}}
+{{#isEnum}}{{>enum}}{{/isEnum}}{{^isEnum}}{{>class}}{{/isEnum}}
+{{/model}}
+{{/models}}
diff --git a/samples/client/petstore/dart/swagger/.swagger-codegen/VERSION b/samples/client/petstore/dart/swagger/.swagger-codegen/VERSION
index 7fea99011a6f..f9f7450d1359 100644
--- a/samples/client/petstore/dart/swagger/.swagger-codegen/VERSION
+++ b/samples/client/petstore/dart/swagger/.swagger-codegen/VERSION
@@ -1 +1 @@
-2.2.3-SNAPSHOT
\ No newline at end of file
+2.3.0-SNAPSHOT
\ No newline at end of file
diff --git a/samples/client/petstore/dart/swagger/docs/StoreApi.md b/samples/client/petstore/dart/swagger/docs/StoreApi.md
index c2e5dcdfde18..b2615f0d4f56 100644
--- a/samples/client/petstore/dart/swagger/docs/StoreApi.md
+++ b/samples/client/petstore/dart/swagger/docs/StoreApi.md
@@ -87,7 +87,7 @@ This endpoint does not need any parameter.
 
 ### Return type
 
-[**Map<String, int>**](Map.md)
+**Map<String, int>**
 
 ### Authorization
 
diff --git a/samples/client/petstore/dart/swagger/lib/api.dart b/samples/client/petstore/dart/swagger/lib/api.dart
index 9273d7f1f99f..79a83321fa57 100644
--- a/samples/client/petstore/dart/swagger/lib/api.dart
+++ b/samples/client/petstore/dart/swagger/lib/api.dart
@@ -6,6 +6,7 @@ import 'package:http/browser_client.dart';
 import 'package:http/http.dart';
 import 'package:dartson/dartson.dart';
 import 'package:dartson/transformers/date_time.dart';
+import 'package:dartson/type_transformer.dart';
 
 part 'api_client.dart';
 part 'api_helper.dart';
@@ -28,4 +29,3 @@ part 'model/user.dart';
 
 
 ApiClient defaultApiClient = new ApiClient();
-
diff --git a/samples/client/petstore/dart/swagger/lib/api_client.dart b/samples/client/petstore/dart/swagger/lib/api_client.dart
index 9552cef10d85..6c292b973f0b 100644
--- a/samples/client/petstore/dart/swagger/lib/api_client.dart
+++ b/samples/client/petstore/dart/swagger/lib/api_client.dart
@@ -16,7 +16,7 @@ class ApiClient {
   Map<String, Authentication> _authentications = {};
 
   final dson = new Dartson.JSON()
-                   ..addTransformer(new DateTimeParser(), DateTime);
+      ..addTransformer(new DateTimeParser(), DateTime);
 
   final _RegList = new RegExp(r'^List<(.*)>$');
   final _RegMap = new RegExp(r'^Map<String,(.*)>$');
@@ -121,7 +121,7 @@ class ApiClient {
     headerParams['Content-Type'] = contentType;
 
     if(body is MultipartRequest) {
-      var request = new MultipartRequest(method, Uri.parse(url));      
+      var request = new MultipartRequest(method, Uri.parse(url));
       request.fields.addAll(body.fields);
       request.files.addAll(body.files);
       request.headers.addAll(body.headers);
@@ -146,7 +146,7 @@ class ApiClient {
   }
 
   /// Update query and header parameters based on authentication settings.
-  /// @param authNames The authentications to apply  
+  /// @param authNames The authentications to apply
   void _updateParamsForAuth(List<String> authNames, List<QueryParam> queryParams, Map<String, String> headerParams) {
     authNames.forEach((authName) {
       Authentication auth = _authentications[authName];
diff --git a/samples/client/petstore/dart/swagger/lib/model/api_response.dart b/samples/client/petstore/dart/swagger/lib/model/api_response.dart
index b2ac2c2577e3..7cb79fb8aef5 100644
--- a/samples/client/petstore/dart/swagger/lib/model/api_response.dart
+++ b/samples/client/petstore/dart/swagger/lib/model/api_response.dart
@@ -1,6 +1,5 @@
 part of swagger.api;
 
-
 @Entity()
 class ApiResponse {
   
@@ -21,6 +20,5 @@ class ApiResponse {
   String toString()  {
     return 'ApiResponse[code=$code, type=$type, message=$message, ]';
   }
-
 }
 
diff --git a/samples/client/petstore/dart/swagger/lib/model/category.dart b/samples/client/petstore/dart/swagger/lib/model/category.dart
index 9ab2a96fc371..26b902731632 100644
--- a/samples/client/petstore/dart/swagger/lib/model/category.dart
+++ b/samples/client/petstore/dart/swagger/lib/model/category.dart
@@ -1,6 +1,5 @@
 part of swagger.api;
 
-
 @Entity()
 class Category {
   
@@ -17,6 +16,5 @@ class Category {
   String toString()  {
     return 'Category[id=$id, name=$name, ]';
   }
-
 }
 
diff --git a/samples/client/petstore/dart/swagger/lib/model/order.dart b/samples/client/petstore/dart/swagger/lib/model/order.dart
index d7ea97b3bad6..84e4a972d57b 100644
--- a/samples/client/petstore/dart/swagger/lib/model/order.dart
+++ b/samples/client/petstore/dart/swagger/lib/model/order.dart
@@ -1,6 +1,5 @@
 part of swagger.api;
 
-
 @Entity()
 class Order {
   
@@ -33,6 +32,5 @@ class Order {
   String toString()  {
     return 'Order[id=$id, petId=$petId, quantity=$quantity, shipDate=$shipDate, status=$status, complete=$complete, ]';
   }
-
 }
 
diff --git a/samples/client/petstore/dart/swagger/lib/model/pet.dart b/samples/client/petstore/dart/swagger/lib/model/pet.dart
index 03e137437634..f2b4108b892c 100644
--- a/samples/client/petstore/dart/swagger/lib/model/pet.dart
+++ b/samples/client/petstore/dart/swagger/lib/model/pet.dart
@@ -1,6 +1,5 @@
 part of swagger.api;
 
-
 @Entity()
 class Pet {
   
@@ -33,6 +32,5 @@ class Pet {
   String toString()  {
     return 'Pet[id=$id, category=$category, name=$name, photoUrls=$photoUrls, tags=$tags, status=$status, ]';
   }
-
 }
 
diff --git a/samples/client/petstore/dart/swagger/lib/model/tag.dart b/samples/client/petstore/dart/swagger/lib/model/tag.dart
index 485de92a6158..45f3668b3e7f 100644
--- a/samples/client/petstore/dart/swagger/lib/model/tag.dart
+++ b/samples/client/petstore/dart/swagger/lib/model/tag.dart
@@ -1,6 +1,5 @@
 part of swagger.api;
 
-
 @Entity()
 class Tag {
   
@@ -17,6 +16,5 @@ class Tag {
   String toString()  {
     return 'Tag[id=$id, name=$name, ]';
   }
-
 }
 
diff --git a/samples/client/petstore/dart/swagger/lib/model/user.dart b/samples/client/petstore/dart/swagger/lib/model/user.dart
index f529d9432c1c..77c021144288 100644
--- a/samples/client/petstore/dart/swagger/lib/model/user.dart
+++ b/samples/client/petstore/dart/swagger/lib/model/user.dart
@@ -1,6 +1,5 @@
 part of swagger.api;
 
-
 @Entity()
 class User {
   
@@ -41,6 +40,5 @@ class User {
   String toString()  {
     return 'User[id=$id, username=$username, firstName=$firstName, lastName=$lastName, email=$email, password=$password, phone=$phone, userStatus=$userStatus, ]';
   }
-
 }