From d9eea48152d9b806be49aaf97985bde845d14c74 Mon Sep 17 00:00:00 2001
From: Guy Gershoni <guy@flipgroup.com.au>
Date: Wed, 7 Nov 2018 09:20:33 +1100
Subject: [PATCH 1/2] Added tests and fix for issue #1392. Param validation
 with regex not recognizing \d correctly in Ruby client.

---
 .../languages/AbstractRubyCodegen.java        | 17 ++++++
 .../ruby-client/Gemfile.lock.mustache         |  2 +-
 .../codegen/ruby/RubyClientCodegenTest.java   | 28 +++++++++
 ...ith-fake-endpoints-models-for-testing.yaml |  8 +++
 .../src/test/resources/3_0/test_regex.yaml    | 51 ++++++++++++++++
 samples/client/petstore/ruby/Gemfile.lock     |  2 +-
 .../client/petstore/ruby/docs/FormatTest.md   |  2 +
 .../ruby/lib/petstore/models/format_test.rb   | 58 +++++++++++++++++--
 .../ruby/spec/models/format_test_spec.rb      | 27 +++++++++
 9 files changed, 189 insertions(+), 6 deletions(-)
 create mode 100644 modules/openapi-generator/src/test/resources/3_0/test_regex.yaml

diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java
index 42f5d8a54ba..754d825016b 100644
--- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java
+++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/AbstractRubyCodegen.java
@@ -146,6 +146,23 @@ abstract class AbstractRubyCodegen extends DefaultCodegen implements CodegenConf
         return name;
     }
 
+    public String toRegularExpression(String pattern) {
+        if (StringUtils.isEmpty(pattern)) {
+            return pattern;
+        }
+
+        // We don't escape \ in string since Ruby doesn't like \ escaped in regex literal
+        String regexString = pattern;
+        if (!regexString.startsWith("/")) {
+            regexString = "/" + regexString;
+        }
+        if (StringUtils.countMatches(regexString, '/') == 1) {
+            // we only have forward slash inserted at start... adding one to end
+            regexString = regexString + "/";
+        }
+        return regexString;
+    }
+
     @Override
     public String toParamName(String name) {
         // should be the same as variable name
diff --git a/modules/openapi-generator/src/main/resources/ruby-client/Gemfile.lock.mustache b/modules/openapi-generator/src/main/resources/ruby-client/Gemfile.lock.mustache
index bb7eb9d3f79..6ba95d4e7a4 100644
--- a/modules/openapi-generator/src/main/resources/ruby-client/Gemfile.lock.mustache
+++ b/modules/openapi-generator/src/main/resources/ruby-client/Gemfile.lock.mustache
@@ -13,7 +13,7 @@ GEM
       public_suffix (>= 2.0.2, < 4.0)
     autotest (4.4.6)
       ZenTest (>= 4.4.1)
-    autotest-fsevent (0.2.13)
+    autotest-fsevent (0.2.14)
       sys-uname
     autotest-growl (0.2.16)
     autotest-rails-pure (4.1.2)
diff --git a/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java b/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java
index 604e601c325..9bb5e0f0464 100644
--- a/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java
+++ b/modules/openapi-generator/src/test/java/org/openapitools/codegen/ruby/RubyClientCodegenTest.java
@@ -300,4 +300,32 @@ public class RubyClientCodegenTest {
         CodegenParameter pp = op.pathParams.get(0);
         Assert.assertEquals(pp.example, "'orderid123'");
     }
+
+    /**
+     * We want to make sure that all Regex patterns:
+     *  - Start with / so Ruby know this is a regex pattern
+     *  - Have a second / that may be added to end if only 1 exists at start
+     *  - If there are 2 / in pattern then don't add any more
+     */
+    @Test(description = "test regex patterns")
+    public void exampleRegexParameterValidationOAS3Test() {
+        final OpenAPI openAPI = new OpenAPIParser()
+                .readLocation("src/test/resources/3_0/test_regex.yaml", null, new ParseOptions()).getOpenAPI();
+        final RubyClientCodegen codegen = new RubyClientCodegen();
+        final String path = "/ping";
+        final Operation p = openAPI.getPaths().get(path).getGet();
+        final CodegenOperation op = codegen.fromOperation(path, "get", p, openAPI.getComponents().getSchemas());
+        // pattern_no_forward_slashes '^pattern$'
+        Assert.assertEquals(op.allParams.get(0).pattern, "/^pattern$/");
+        // pattern_two_slashes '/^pattern$/i'
+        Assert.assertEquals(op.allParams.get(1).pattern, "/^pattern$/i");
+        // pattern_one_slash_start '/^pattern$'
+        Assert.assertEquals(op.allParams.get(2).pattern, "/^pattern$/");
+        // pattern_one_slash_end '^pattern$/'
+        Assert.assertEquals(op.allParams.get(3).pattern, "/^pattern$/");
+        // pattern_one_slash_near_end '^pattern$/im'
+        Assert.assertEquals(op.allParams.get(4).pattern, "/^pattern$/im");
+        // pattern_dont_escape_backslash '/^pattern\d{3}$/i' NOTE: the double \ is to escape \ in string but is read as single \
+        Assert.assertEquals(op.allParams.get(5).pattern, "/^pattern\\d{3}$/i");
+    }
 }
diff --git a/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml b/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
index 1348fbaee05..d60c17ddc3a 100644
--- a/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
+++ b/modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
@@ -1338,6 +1338,14 @@ components:
           format: password
           maxLength: 64
           minLength: 10
+        pattern_with_digits:
+          description: A string that is a 10 digit number. Can have leading zeros. 
+          type: string
+          pattern: '^\d{10}$'
+        pattern_with_digits_and_delimiter:
+          description: A string starting with 'image_' (case insensitive) and one to three digits following i.e. Image_01.
+          type: string
+          pattern: '/^image_\d{1,3}$/i'
     EnumClass:
       type: string
       default: '-efg'
diff --git a/modules/openapi-generator/src/test/resources/3_0/test_regex.yaml b/modules/openapi-generator/src/test/resources/3_0/test_regex.yaml
new file mode 100644
index 00000000000..af1ae8d3101
--- /dev/null
+++ b/modules/openapi-generator/src/test/resources/3_0/test_regex.yaml
@@ -0,0 +1,51 @@
+openapi: 3.0.1
+info:
+  title: Test Regex generation for parameter validation
+  version: 1.0.0
+components:
+  headers:
+
+  responses:
+    OK_200:
+      description: OK
+
+paths:
+  /ping:
+    get:
+      summary: Get Payment Information
+      description: Returns the content of a payment object
+      parameters:
+        - name: pattern_no_forward_slashes
+          in: header
+          schema:
+            type: string
+            pattern: '^pattern$'
+        - name: pattern_two_slashes
+          in: header
+          schema:
+            type: string
+            pattern: '/^pattern$/i'
+        - name: pattern_one_slash_start
+          in: header
+          schema:
+            type: string
+            pattern: '/^pattern$'
+        - name: pattern_one_slash_end
+          in: header
+          schema:
+            type: string
+            pattern: '^pattern$/'
+        - name: pattern_one_slash_near_end
+          in: header
+          schema:
+            type: string
+            pattern: '^pattern$/im'
+        - name: pattern_dont_escape_backslash
+          in: header
+          schema:
+            type: string
+            pattern: '/^pattern\d{3}$/i'
+
+      responses:
+        '200':
+          $ref: "#/components/responses/OK_200"
diff --git a/samples/client/petstore/ruby/Gemfile.lock b/samples/client/petstore/ruby/Gemfile.lock
index 0a4edb9a91b..995e71af95b 100644
--- a/samples/client/petstore/ruby/Gemfile.lock
+++ b/samples/client/petstore/ruby/Gemfile.lock
@@ -13,7 +13,7 @@ GEM
       public_suffix (>= 2.0.2, < 4.0)
     autotest (4.4.6)
       ZenTest (>= 4.4.1)
-    autotest-fsevent (0.2.13)
+    autotest-fsevent (0.2.14)
       sys-uname
     autotest-growl (0.2.16)
     autotest-rails-pure (4.1.2)
diff --git a/samples/client/petstore/ruby/docs/FormatTest.md b/samples/client/petstore/ruby/docs/FormatTest.md
index ad9b8191dce..8682ea539e8 100644
--- a/samples/client/petstore/ruby/docs/FormatTest.md
+++ b/samples/client/petstore/ruby/docs/FormatTest.md
@@ -16,5 +16,7 @@ Name | Type | Description | Notes
 **date_time** | **DateTime** |  | [optional] 
 **uuid** | **String** |  | [optional] 
 **password** | **String** |  | 
+**pattern_with_digits** | **String** | A string that is a 10 digit number. Can have leading zeros. | [optional] 
+**pattern_with_digits_and_delimiter** | **String** | A string starting with &#39;image_&#39; (case insensitive) and one to three digits following i.e. Image_01. | [optional] 
 
 
diff --git a/samples/client/petstore/ruby/lib/petstore/models/format_test.rb b/samples/client/petstore/ruby/lib/petstore/models/format_test.rb
index 35b1d90b039..9a5dbb7671d 100644
--- a/samples/client/petstore/ruby/lib/petstore/models/format_test.rb
+++ b/samples/client/petstore/ruby/lib/petstore/models/format_test.rb
@@ -40,6 +40,12 @@ module Petstore
 
     attr_accessor :password
 
+    # A string that is a 10 digit number. Can have leading zeros.
+    attr_accessor :pattern_with_digits
+
+    # A string starting with 'image_' (case insensitive) and one to three digits following i.e. Image_01.
+    attr_accessor :pattern_with_digits_and_delimiter
+
     # Attribute mapping from ruby-style variable name to JSON key.
     def self.attribute_map
       {
@@ -55,7 +61,9 @@ module Petstore
         :'date' => :'date',
         :'date_time' => :'dateTime',
         :'uuid' => :'uuid',
-        :'password' => :'password'
+        :'password' => :'password',
+        :'pattern_with_digits' => :'pattern_with_digits',
+        :'pattern_with_digits_and_delimiter' => :'pattern_with_digits_and_delimiter'
       }
     end
 
@@ -74,7 +82,9 @@ module Petstore
         :'date' => :'Date',
         :'date_time' => :'DateTime',
         :'uuid' => :'String',
-        :'password' => :'String'
+        :'password' => :'String',
+        :'pattern_with_digits' => :'String',
+        :'pattern_with_digits_and_delimiter' => :'String'
       }
     end
 
@@ -137,6 +147,14 @@ module Petstore
       if attributes.has_key?(:'password')
         self.password = attributes[:'password']
       end
+
+      if attributes.has_key?(:'pattern_with_digits')
+        self.pattern_with_digits = attributes[:'pattern_with_digits']
+      end
+
+      if attributes.has_key?(:'pattern_with_digits_and_delimiter')
+        self.pattern_with_digits_and_delimiter = attributes[:'pattern_with_digits_and_delimiter']
+      end
     end
 
     # Show invalid properties with the reasons. Usually used together with valid?
@@ -211,6 +229,14 @@ module Petstore
         invalid_properties.push('invalid value for "password", the character length must be great than or equal to 10.')
       end
 
+      if !@pattern_with_digits.nil? && @pattern_with_digits !~ Regexp.new(/^\d{10}$/)
+        invalid_properties.push('invalid value for "pattern_with_digits", must conform to the pattern /^\d{10}$/.')
+      end
+
+      if !@pattern_with_digits_and_delimiter.nil? && @pattern_with_digits_and_delimiter !~ Regexp.new(/^image_\d{1,3}$/i)
+        invalid_properties.push('invalid value for "pattern_with_digits_and_delimiter", must conform to the pattern /^image_\d{1,3}$/i.')
+      end
+
       invalid_properties
     end
 
@@ -234,6 +260,8 @@ module Petstore
       return false if @password.nil?
       return false if @password.to_s.length > 64
       return false if @password.to_s.length < 10
+      return false if !@pattern_with_digits.nil? && @pattern_with_digits !~ Regexp.new(/^\d{10}$/)
+      return false if !@pattern_with_digits_and_delimiter.nil? && @pattern_with_digits_and_delimiter !~ Regexp.new(/^image_\d{1,3}$/i)
       true
     end
 
@@ -339,6 +367,26 @@ module Petstore
       @password = password
     end
 
+    # Custom attribute writer method with validation
+    # @param [Object] pattern_with_digits Value to be assigned
+    def pattern_with_digits=(pattern_with_digits)
+      if !pattern_with_digits.nil? && pattern_with_digits !~ Regexp.new(/^\d{10}$/)
+        fail ArgumentError, 'invalid value for "pattern_with_digits", must conform to the pattern /^\d{10}$/.'
+      end
+
+      @pattern_with_digits = pattern_with_digits
+    end
+
+    # Custom attribute writer method with validation
+    # @param [Object] pattern_with_digits_and_delimiter Value to be assigned
+    def pattern_with_digits_and_delimiter=(pattern_with_digits_and_delimiter)
+      if !pattern_with_digits_and_delimiter.nil? && pattern_with_digits_and_delimiter !~ Regexp.new(/^image_\d{1,3}$/i)
+        fail ArgumentError, 'invalid value for "pattern_with_digits_and_delimiter", must conform to the pattern /^image_\d{1,3}$/i.'
+      end
+
+      @pattern_with_digits_and_delimiter = pattern_with_digits_and_delimiter
+    end
+
     # Checks equality by comparing each attribute.
     # @param [Object] Object to be compared
     def ==(o)
@@ -356,7 +404,9 @@ module Petstore
           date == o.date &&
           date_time == o.date_time &&
           uuid == o.uuid &&
-          password == o.password
+          password == o.password &&
+          pattern_with_digits == o.pattern_with_digits &&
+          pattern_with_digits_and_delimiter == o.pattern_with_digits_and_delimiter
     end
 
     # @see the `==` method
@@ -368,7 +418,7 @@ module Petstore
     # Calculates hash code according to all attributes.
     # @return [Fixnum] Hash code
     def hash
-      [integer, int32, int64, number, float, double, string, byte, binary, date, date_time, uuid, password].hash
+      [integer, int32, int64, number, float, double, string, byte, binary, date, date_time, uuid, password, pattern_with_digits, pattern_with_digits_and_delimiter].hash
     end
 
     # Builds the object from hash
diff --git a/samples/client/petstore/ruby/spec/models/format_test_spec.rb b/samples/client/petstore/ruby/spec/models/format_test_spec.rb
index 2fee049ec96..74f4fe9bedd 100644
--- a/samples/client/petstore/ruby/spec/models/format_test_spec.rb
+++ b/samples/client/petstore/ruby/spec/models/format_test_spec.rb
@@ -110,4 +110,31 @@ describe 'FormatTest' do
     end
   end
 
+  describe 'test attribute "pattern_with_digits"' do
+    it 'should accept string "1234567890"' do
+      @instance.pattern_with_digits = '1234567890'
+    end
+
+    it 'should accept string with leading zero "0123456789"' do
+      @instance.pattern_with_digits = '0123456789'
+    end
+
+    it 'should reject string with non digits "ABC3456789"' do
+      expect {@instance.pattern_with_digits = 'ABC3456789'}.to raise_error(ArgumentError)
+    end
+
+    it 'should reject string less than 10 in length "123456789"' do
+      expect {@instance.pattern_with_digits = '123456789'}.to raise_error(ArgumentError)
+    end
+
+    it 'should reject string more than 10 in length "0123456789123"' do
+      expect {@instance.pattern_with_digits = '0123456789123'}.to raise_error(ArgumentError)
+    end
+  end
+
+  describe 'test attribute "pattern_with_digits_and_delimiter"' do
+    it 'should accept string "Image_01"' do
+      @instance.pattern_with_digits_and_delimiter = 'Image_01'
+    end
+  end
 end
-- 
GitLab


From 3cb314fc6806c9d7dadf3144fd11e759d927db2a Mon Sep 17 00:00:00 2001
From: Guy Gershoni <guy@flipgroup.com.au>
Date: Wed, 7 Nov 2018 10:57:34 +1100
Subject: [PATCH 2/2] Added generated files to pass
 ./bin/utils/ensure-up-to-date which is run by circleci

---
 .../docs/Model/FormatTest.md                  |  2 +
 .../lib/Model/FormatTest.php                  | 88 +++++++++++++++++--
 .../test/Model/FormatTestTest.php             | 14 +++
 .../org/openapitools/model/FormatTest.java    | 54 +++++++++++-
 4 files changed, 151 insertions(+), 7 deletions(-)

diff --git a/samples/openapi3/client/petstore/php/OpenAPIClient-php/docs/Model/FormatTest.md b/samples/openapi3/client/petstore/php/OpenAPIClient-php/docs/Model/FormatTest.md
index e106ff1eba2..c27cc2cf209 100644
--- a/samples/openapi3/client/petstore/php/OpenAPIClient-php/docs/Model/FormatTest.md
+++ b/samples/openapi3/client/petstore/php/OpenAPIClient-php/docs/Model/FormatTest.md
@@ -16,6 +16,8 @@ Name | Type | Description | Notes
 **date_time** | [**\DateTime**](\DateTime.md) |  | [optional] 
 **uuid** | **string** |  | [optional] 
 **password** | **string** |  | 
+**pattern_with_digits** | **string** | A string that is a 10 digit number. Can have leading zeros. | [optional] 
+**pattern_with_digits_and_delimiter** | **string** | A string starting with &#39;image_&#39; (case insensitive) and one to three digits following i.e. Image_01. | [optional] 
 
 [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
 
diff --git a/samples/openapi3/client/petstore/php/OpenAPIClient-php/lib/Model/FormatTest.php b/samples/openapi3/client/petstore/php/OpenAPIClient-php/lib/Model/FormatTest.php
index 8519557aaaf..508e7923171 100644
--- a/samples/openapi3/client/petstore/php/OpenAPIClient-php/lib/Model/FormatTest.php
+++ b/samples/openapi3/client/petstore/php/OpenAPIClient-php/lib/Model/FormatTest.php
@@ -69,7 +69,9 @@ class FormatTest implements ModelInterface, ArrayAccess
         'date' => '\DateTime',
         'date_time' => '\DateTime',
         'uuid' => 'string',
-        'password' => 'string'
+        'password' => 'string',
+        'pattern_with_digits' => 'string',
+        'pattern_with_digits_and_delimiter' => 'string'
     ];
 
     /**
@@ -90,7 +92,9 @@ class FormatTest implements ModelInterface, ArrayAccess
         'date' => 'date',
         'date_time' => 'date-time',
         'uuid' => 'uuid',
-        'password' => 'password'
+        'password' => 'password',
+        'pattern_with_digits' => null,
+        'pattern_with_digits_and_delimiter' => null
     ];
 
     /**
@@ -132,7 +136,9 @@ class FormatTest implements ModelInterface, ArrayAccess
         'date' => 'date',
         'date_time' => 'dateTime',
         'uuid' => 'uuid',
-        'password' => 'password'
+        'password' => 'password',
+        'pattern_with_digits' => 'pattern_with_digits',
+        'pattern_with_digits_and_delimiter' => 'pattern_with_digits_and_delimiter'
     ];
 
     /**
@@ -153,7 +159,9 @@ class FormatTest implements ModelInterface, ArrayAccess
         'date' => 'setDate',
         'date_time' => 'setDateTime',
         'uuid' => 'setUuid',
-        'password' => 'setPassword'
+        'password' => 'setPassword',
+        'pattern_with_digits' => 'setPatternWithDigits',
+        'pattern_with_digits_and_delimiter' => 'setPatternWithDigitsAndDelimiter'
     ];
 
     /**
@@ -174,7 +182,9 @@ class FormatTest implements ModelInterface, ArrayAccess
         'date' => 'getDate',
         'date_time' => 'getDateTime',
         'uuid' => 'getUuid',
-        'password' => 'getPassword'
+        'password' => 'getPassword',
+        'pattern_with_digits' => 'getPatternWithDigits',
+        'pattern_with_digits_and_delimiter' => 'getPatternWithDigitsAndDelimiter'
     ];
 
     /**
@@ -250,6 +260,8 @@ class FormatTest implements ModelInterface, ArrayAccess
         $this->container['date_time'] = isset($data['date_time']) ? $data['date_time'] : null;
         $this->container['uuid'] = isset($data['uuid']) ? $data['uuid'] : null;
         $this->container['password'] = isset($data['password']) ? $data['password'] : null;
+        $this->container['pattern_with_digits'] = isset($data['pattern_with_digits']) ? $data['pattern_with_digits'] : null;
+        $this->container['pattern_with_digits_and_delimiter'] = isset($data['pattern_with_digits_and_delimiter']) ? $data['pattern_with_digits_and_delimiter'] : null;
     }
 
     /**
@@ -325,6 +337,14 @@ class FormatTest implements ModelInterface, ArrayAccess
             $invalidProperties[] = "invalid value for 'password', the character length must be bigger than or equal to 10.";
         }
 
+        if (!is_null($this->container['pattern_with_digits']) && !preg_match("/^\\d{10}$/", $this->container['pattern_with_digits'])) {
+            $invalidProperties[] = "invalid value for 'pattern_with_digits', must be conform to the pattern /^\\d{10}$/.";
+        }
+
+        if (!is_null($this->container['pattern_with_digits_and_delimiter']) && !preg_match("/^image_\\d{1,3}$/i", $this->container['pattern_with_digits_and_delimiter'])) {
+            $invalidProperties[] = "invalid value for 'pattern_with_digits_and_delimiter', must be conform to the pattern /^image_\\d{1,3}$/i.";
+        }
+
         return $invalidProperties;
     }
 
@@ -703,6 +723,64 @@ class FormatTest implements ModelInterface, ArrayAccess
 
         return $this;
     }
+
+    /**
+     * Gets pattern_with_digits
+     *
+     * @return string|null
+     */
+    public function getPatternWithDigits()
+    {
+        return $this->container['pattern_with_digits'];
+    }
+
+    /**
+     * Sets pattern_with_digits
+     *
+     * @param string|null $pattern_with_digits A string that is a 10 digit number. Can have leading zeros.
+     *
+     * @return $this
+     */
+    public function setPatternWithDigits($pattern_with_digits)
+    {
+
+        if (!is_null($pattern_with_digits) && (!preg_match("/^\\d{10}$/", $pattern_with_digits))) {
+            throw new \InvalidArgumentException("invalid value for $pattern_with_digits when calling FormatTest., must conform to the pattern /^\\d{10}$/.");
+        }
+
+        $this->container['pattern_with_digits'] = $pattern_with_digits;
+
+        return $this;
+    }
+
+    /**
+     * Gets pattern_with_digits_and_delimiter
+     *
+     * @return string|null
+     */
+    public function getPatternWithDigitsAndDelimiter()
+    {
+        return $this->container['pattern_with_digits_and_delimiter'];
+    }
+
+    /**
+     * Sets pattern_with_digits_and_delimiter
+     *
+     * @param string|null $pattern_with_digits_and_delimiter A string starting with 'image_' (case insensitive) and one to three digits following i.e. Image_01.
+     *
+     * @return $this
+     */
+    public function setPatternWithDigitsAndDelimiter($pattern_with_digits_and_delimiter)
+    {
+
+        if (!is_null($pattern_with_digits_and_delimiter) && (!preg_match("/^image_\\d{1,3}$/i", $pattern_with_digits_and_delimiter))) {
+            throw new \InvalidArgumentException("invalid value for $pattern_with_digits_and_delimiter when calling FormatTest., must conform to the pattern /^image_\\d{1,3}$/i.");
+        }
+
+        $this->container['pattern_with_digits_and_delimiter'] = $pattern_with_digits_and_delimiter;
+
+        return $this;
+    }
     /**
      * Returns true if offset exists. False otherwise.
      *
diff --git a/samples/openapi3/client/petstore/php/OpenAPIClient-php/test/Model/FormatTestTest.php b/samples/openapi3/client/petstore/php/OpenAPIClient-php/test/Model/FormatTestTest.php
index bb4992a126b..ffc01b4eb80 100644
--- a/samples/openapi3/client/petstore/php/OpenAPIClient-php/test/Model/FormatTestTest.php
+++ b/samples/openapi3/client/petstore/php/OpenAPIClient-php/test/Model/FormatTestTest.php
@@ -166,4 +166,18 @@ class FormatTestTest extends \PHPUnit_Framework_TestCase
     public function testPropertyPassword()
     {
     }
+
+    /**
+     * Test attribute "pattern_with_digits"
+     */
+    public function testPropertyPatternWithDigits()
+    {
+    }
+
+    /**
+     * Test attribute "pattern_with_digits_and_delimiter"
+     */
+    public function testPropertyPatternWithDigitsAndDelimiter()
+    {
+    }
 }
diff --git a/samples/server/petstore/jaxrs-jersey/src/gen/java/org/openapitools/model/FormatTest.java b/samples/server/petstore/jaxrs-jersey/src/gen/java/org/openapitools/model/FormatTest.java
index cbeec51b83b..6cb07696525 100644
--- a/samples/server/petstore/jaxrs-jersey/src/gen/java/org/openapitools/model/FormatTest.java
+++ b/samples/server/petstore/jaxrs-jersey/src/gen/java/org/openapitools/model/FormatTest.java
@@ -69,6 +69,12 @@ public class FormatTest   {
   @JsonProperty("password")
   private String password;
 
+  @JsonProperty("pattern_with_digits")
+  private String patternWithDigits;
+
+  @JsonProperty("pattern_with_digits_and_delimiter")
+  private String patternWithDigitsAndDelimiter;
+
   public FormatTest integer(Integer integer) {
     this.integer = integer;
     return this;
@@ -343,6 +349,46 @@ public class FormatTest   {
     this.password = password;
   }
 
+  public FormatTest patternWithDigits(String patternWithDigits) {
+    this.patternWithDigits = patternWithDigits;
+    return this;
+  }
+
+  /**
+   * A string that is a 10 digit number. Can have leading zeros.
+   * @return patternWithDigits
+   **/
+  @JsonProperty("pattern_with_digits")
+  @ApiModelProperty(value = "A string that is a 10 digit number. Can have leading zeros.")
+   @Pattern(regexp="^\\d{10}$")
+  public String getPatternWithDigits() {
+    return patternWithDigits;
+  }
+
+  public void setPatternWithDigits(String patternWithDigits) {
+    this.patternWithDigits = patternWithDigits;
+  }
+
+  public FormatTest patternWithDigitsAndDelimiter(String patternWithDigitsAndDelimiter) {
+    this.patternWithDigitsAndDelimiter = patternWithDigitsAndDelimiter;
+    return this;
+  }
+
+  /**
+   * A string starting with &#39;image_&#39; (case insensitive) and one to three digits following i.e. Image_01.
+   * @return patternWithDigitsAndDelimiter
+   **/
+  @JsonProperty("pattern_with_digits_and_delimiter")
+  @ApiModelProperty(value = "A string starting with 'image_' (case insensitive) and one to three digits following i.e. Image_01.")
+   @Pattern(regexp="/^image_\\d{1,3}$/i")
+  public String getPatternWithDigitsAndDelimiter() {
+    return patternWithDigitsAndDelimiter;
+  }
+
+  public void setPatternWithDigitsAndDelimiter(String patternWithDigitsAndDelimiter) {
+    this.patternWithDigitsAndDelimiter = patternWithDigitsAndDelimiter;
+  }
+
 
   @Override
   public boolean equals(java.lang.Object o) {
@@ -365,12 +411,14 @@ public class FormatTest   {
         Objects.equals(this.date, formatTest.date) &&
         Objects.equals(this.dateTime, formatTest.dateTime) &&
         Objects.equals(this.uuid, formatTest.uuid) &&
-        Objects.equals(this.password, formatTest.password);
+        Objects.equals(this.password, formatTest.password) &&
+        Objects.equals(this.patternWithDigits, formatTest.patternWithDigits) &&
+        Objects.equals(this.patternWithDigitsAndDelimiter, formatTest.patternWithDigitsAndDelimiter);
   }
 
   @Override
   public int hashCode() {
-    return Objects.hash(integer, int32, int64, number, _float, _double, string, _byte, binary, date, dateTime, uuid, password);
+    return Objects.hash(integer, int32, int64, number, _float, _double, string, _byte, binary, date, dateTime, uuid, password, patternWithDigits, patternWithDigitsAndDelimiter);
   }
 
 
@@ -392,6 +440,8 @@ public class FormatTest   {
     sb.append("    dateTime: ").append(toIndentedString(dateTime)).append("\n");
     sb.append("    uuid: ").append(toIndentedString(uuid)).append("\n");
     sb.append("    password: ").append(toIndentedString(password)).append("\n");
+    sb.append("    patternWithDigits: ").append(toIndentedString(patternWithDigits)).append("\n");
+    sb.append("    patternWithDigitsAndDelimiter: ").append(toIndentedString(patternWithDigitsAndDelimiter)).append("\n");
     sb.append("}");
     return sb.toString();
   }
-- 
GitLab