Merge branch 'master' into master
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index f2f6c07..706d08b 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -45,10 +45,10 @@
 
     steps:
     - name: Checkout repository
-      uses: actions/checkout@v3.5.0
+      uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
       with:
         persist-credentials: false
-    - uses: actions/cache@v3.3.1
+    - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
       with:
         path: ~/.m2/repository
         key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
@@ -57,7 +57,7 @@
 
     # Initializes the CodeQL tools for scanning.
     - name: Initialize CodeQL
-      uses: github/codeql-action/init@v2
+      uses: github/codeql-action/init@1b1aada464948af03b950897e5eb522f92603cc2    # 3.24.9
       with:
         languages: ${{ matrix.language }}
         # If you wish to specify custom queries, you can do so here or in a config file.
@@ -68,7 +68,7 @@
     # Autobuild attempts to build any compiled languages  (C/C++, C#, or Java).
     # If this step fails, then you should remove it and run the build manually (see below)
     - name: Autobuild
-      uses: github/codeql-action/autobuild@v2
+      uses: github/codeql-action/autobuild@1b1aada464948af03b950897e5eb522f92603cc2    # 3.24.9
 
     # ℹī¸ Command-line programs to run using the OS shell.
     # 📚 https://git.io/JvXDl
@@ -82,4 +82,4 @@
     #   make release
 
     - name: Perform CodeQL Analysis
-      uses: github/codeql-action/analyze@v2
+      uses: github/codeql-action/analyze@1b1aada464948af03b950897e5eb522f92603cc2    # 3.24.9
diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml
index 06a2b95..8036df1 100644
--- a/.github/workflows/coverage.yml
+++ b/.github/workflows/coverage.yml
@@ -29,24 +29,24 @@
         java: [ 8 ]
 
     steps:
-    - uses: actions/checkout@v3.5.0
+    - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
       with:
         persist-credentials: false
-    - uses: actions/cache@v3.3.1
+    - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
       with:
         path: ~/.m2/repository
         key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
         restore-keys: |
           ${{ runner.os }}-maven-
     - name: Set up JDK ${{ matrix.java }}
-      uses: actions/setup-java@v3.11.0
+      uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
       with:
         distribution: 'temurin'
         java-version: ${{ matrix.java }}
     - name: Build with Maven
-      run: mvn -V test jacoco:report --file pom.xml --no-transfer-progress
+      run: mvn --show-version --batch-mode --no-transfer-progress test jacoco:report
 
     - name: Upload coverage to Codecov
-      uses: codecov/codecov-action@v3
+      uses: codecov/codecov-action@54bcd8715eee62d40e33596ef5e8f0f48dbbccab # v4.1.0
       with:
         files: ./target/site/jacoco/jacoco.xml
diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml
index d924321..682c69c 100644
--- a/.github/workflows/maven.yml
+++ b/.github/workflows/maven.yml
@@ -27,26 +27,26 @@
     continue-on-error: ${{ matrix.experimental }}

     strategy:

       matrix:

-        java: [ 8, 11, 17 ]

+        java: [ 8, 11, 17, 21 ]

         experimental: [false]

 #        include:

-#          - java: 18-ea

+#          - java: 22-ea

 #            experimental: true        

         

     steps:

-    - uses: actions/checkout@v3.5.0

+    - uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
       with:
         persist-credentials: false
-    - uses: actions/cache@v3.3.1

+    - uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
       with:

         path: ~/.m2/repository

         key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}

         restore-keys: |

           ${{ runner.os }}-maven-

     - name: Set up JDK ${{ matrix.java }}

-      uses: actions/setup-java@v3.11.0

+      uses: actions/setup-java@99b8673ff64fbf99d8d325f52d9a5bdedb8483e9 # v4.2.1
       with:

         distribution: 'temurin'

         java-version: ${{ matrix.java }}

     - name: Build with Maven

-      run: mvn -V --batch-mode -Ddoclint=all --file pom.xml --no-transfer-progress

+      run: mvn --show-version --batch-mode --no-transfer-progress -Ddoclint=all

diff --git a/.github/workflows/scorecards-analysis.yml b/.github/workflows/scorecards-analysis.yml
index 52a440a..e16004d 100644
--- a/.github/workflows/scorecards-analysis.yml
+++ b/.github/workflows/scorecards-analysis.yml
@@ -40,12 +40,12 @@
     steps:
 
       - name: "Checkout code"
-        uses: actions/checkout@v3.5.0   # 3.1.0
+        uses: actions/checkout@9bb56186c3b09b4f86b1c65136769dd318469633 # v4.1.2
         with:
           persist-credentials: false
 
       - name: "Run analysis"
-        uses: ossf/scorecard-action@80e868c13c90f172d68d1f4501dee99e2479f7af    # 2.1.3
+        uses: ossf/scorecard-action@0864cf19026789058feabb7e87baa5f140aac736    # 2.3.1
         with:
           results_file: results.sarif
           results_format: sarif
@@ -57,13 +57,13 @@
           publish_results: true
 
       - name: "Upload artifact"
-        uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce    # 3.1.0
+        uses: actions/upload-artifact@5d5d22a31266ced268874388b861e4b58bb5c2f3    # 4.3.1
         with:
           name: SARIF file
           path: results.sarif
           retention-days: 5
 
       - name: "Upload to code-scanning"
-        uses: github/codeql-action/upload-sarif@b398f525a5587552e573b247ac661067fafa920b    # 2.1.22
+        uses: github/codeql-action/upload-sarif@1b1aada464948af03b950897e5eb522f92603cc2    # 3.24.9
         with:
           sarif_file: results.sarif
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index c52ef41..5d2f360 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,115 +1,115 @@
-<!---

- Licensed to the Apache Software Foundation (ASF) under one or more

- contributor license agreements.  See the NOTICE file distributed with

- this work for additional information regarding copyright ownership.

- The ASF licenses this file to You under the Apache License, Version 2.0

- (the "License"); you may not use this file except in compliance with

- the License.  You may obtain a copy of the License at

-

-      http://www.apache.org/licenses/LICENSE-2.0

-

- Unless required by applicable law or agreed to in writing, software

- distributed under the License is distributed on an "AS IS" BASIS,

- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- See the License for the specific language governing permissions and

- limitations under the License.

--->

-<!---

- +======================================================================+

- |****                                                              ****|

- |****      THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN      ****|

- |****                    DO NOT EDIT DIRECTLY                      ****|

- |****                                                              ****|

- +======================================================================+

- | TEMPLATE FILE: contributing-md-template.md                           |

- | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |

- +======================================================================+

- |                                                                      |

- | 1) Re-generate using: mvn commons-build:contributing-md              |

- |                                                                      |

- | 2) Set the following properties in the component's pom:              |

- |    - commons.jira.id  (required, alphabetic, upper case)             |

- |                                                                      |

- | 3) Example Properties                                                |

- |                                                                      |

- |  <properties>                                                        |

- |    <commons.jira.id>MATH</commons.jira.id>                           |

- |  </properties>                                                       |

- |                                                                      |

- +======================================================================+

---->

-Contributing to Apache Commons Validator

-======================

-

-You have found a bug or you have an idea for a cool new feature? Contributing code is a great way to give something back to

-the open source community. Before you dig right into the code there are a few guidelines that we need contributors to

-follow so that we can have a chance of keeping on top of things.

-

-Getting Started

----------------

-

-+ Make sure you have a [JIRA account](https://issues.apache.org/jira/).

-+ Make sure you have a [GitHub account](https://github.com/signup/free).

-+ If you're planning to implement a new feature it makes sense to discuss your changes on the [dev list](https://commons.apache.org/mail-lists.html) first. This way you can make sure you're not wasting your time on something that isn't considered to be in Apache Commons Validator's scope.

-+ Submit a [Jira Ticket][jira] for your issue, assuming one does not already exist.

-  + Clearly describe the issue including steps to reproduce when it is a bug.

-  + Make sure you fill in the earliest version that you know has the issue.

-+ Find the corresponding [repository on GitHub](https://github.com/apache/?query=commons-),

-[fork](https://help.github.com/articles/fork-a-repo/) and check out your forked repository.

-

-Making Changes

---------------

-

-+ Create a _topic branch_ for your isolated work.

-  * Usually you should base your branch on the `master` branch.

-  * A good topic branch name can be the JIRA bug id plus a keyword, e.g. `VALIDATOR-123-InputStream`.

-  * If you have submitted multiple JIRA issues, try to maintain separate branches and pull requests.

-+ Make commits of logical units.

-  * Make sure your commit messages are meaningful and in the proper format. Your commit message should contain the key of the JIRA issue.

-  * e.g. `VALIDATOR-123: Close input stream earlier`

-+ Respect the original code style:

-  + Only use spaces for indentation.

-  + Create minimal diffs - disable _On Save_ actions like _Reformat Source Code_ or _Organize Imports_. If you feel the source code should be reformatted create a separate PR for this change first.

-  + Check for unnecessary whitespace with `git diff` -- check before committing.

-+ Make sure you have added the necessary tests for your changes, typically in `src/test/java`.

-+ Run all the tests with `mvn clean verify` to assure nothing else was accidentally broken.

-

-Making Trivial Changes

-----------------------

-

-The JIRA tickets are used to generate the changelog for the next release.

-

-For changes of a trivial nature to comments and documentation, it is not always necessary to create a new ticket in JIRA.

-In this case, it is appropriate to start the first line of a commit with '(doc)' instead of a ticket number.

-

-

-Submitting Changes

-------------------

-

-+ Sign and submit the Apache [Contributor License Agreement][cla] if you haven't already.

-  * Note that small patches & typical bug fixes do not require a CLA as

-    clause 5 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0.html#contributions)

-    covers them.

-+ Push your changes to a topic branch in your fork of the repository.

-+ Submit a _Pull Request_ to the corresponding repository in the `apache` organization.

-  * Verify _Files Changed_ shows only your intended changes and does not

-  include additional files like `target/*.class`

-+ Update your JIRA ticket and include a link to the pull request in the ticket.

-

-If you prefer to not use GitHub, then you can instead use

-`git format-patch` (or `svn diff`) and attach the patch file to the JIRA issue.

-

-

-Additional Resources

---------------------

-

-+ [Contributing patches](https://commons.apache.org/patches.html)

-+ [Apache Commons Validator JIRA project page][jira]

-+ [Contributor License Agreement][cla]

-+ [General GitHub documentation](https://help.github.com/)

-+ [GitHub pull request documentation](https://help.github.com/articles/creating-a-pull-request/)

-+ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)

-+ `#apache-commons` IRC channel on `irc.freenode.net`

-

-[cla]:https://www.apache.org/licenses/#clas

-[jira]:https://issues.apache.org/jira/browse/VALIDATOR

+<!---
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!---
+ +======================================================================+
+ |****                                                              ****|
+ |****      THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN      ****|
+ |****                    DO NOT EDIT DIRECTLY                      ****|
+ |****                                                              ****|
+ +======================================================================+
+ | TEMPLATE FILE: contributing-md-template.md                           |
+ | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
+ +======================================================================+
+ |                                                                      |
+ | 1) Re-generate using: mvn commons-build:contributing-md              |
+ |                                                                      |
+ | 2) Set the following properties in the component's pom:              |
+ |    - commons.jira.id  (required, alphabetic, upper case)             |
+ |                                                                      |
+ | 3) Example Properties                                                |
+ |                                                                      |
+ |  <properties>                                                        |
+ |    <commons.jira.id>MATH</commons.jira.id>                           |
+ |  </properties>                                                       |
+ |                                                                      |
+ +======================================================================+
+--->
+Contributing to Apache Commons Validator
+======================
+
+You have found a bug or you have an idea for a cool new feature? Contributing code is a great way to give something back to
+the open source community. Before you dig right into the code there are a few guidelines that we need contributors to
+follow so that we can have a chance of keeping on top of things.
+
+Getting Started
+---------------
+
++ Make sure you have a [JIRA account](https://issues.apache.org/jira/).
++ Make sure you have a [GitHub account](https://github.com/signup/free).
++ If you're planning to implement a new feature it makes sense to discuss your changes on the [dev list](https://commons.apache.org/mail-lists.html) first. This way you can make sure you're not wasting your time on something that isn't considered to be in Apache Commons Validator's scope.
++ Submit a [Jira Ticket][jira] for your issue, assuming one does not already exist.
+  + Clearly describe the issue including steps to reproduce when it is a bug.
+  + Make sure you fill in the earliest version that you know has the issue.
++ Find the corresponding [repository on GitHub](https://github.com/apache/?query=commons-),
+[fork](https://help.github.com/articles/fork-a-repo/) and check out your forked repository.
+
+Making Changes
+--------------
+
++ Create a _topic branch_ for your isolated work.
+  * Usually you should base your branch on the `master` branch.
+  * A good topic branch name can be the JIRA bug id plus a keyword, e.g. `VALIDATOR-123-InputStream`.
+  * If you have submitted multiple JIRA issues, try to maintain separate branches and pull requests.
++ Make commits of logical units.
+  * Make sure your commit messages are meaningful and in the proper format. Your commit message should contain the key of the JIRA issue.
+  * e.g. `VALIDATOR-123: Close input stream earlier`
++ Respect the original code style:
+  + Only use spaces for indentation.
+  + Create minimal diffs - disable _On Save_ actions like _Reformat Source Code_ or _Organize Imports_. If you feel the source code should be reformatted create a separate PR for this change first.
+  + Check for unnecessary whitespace with `git diff` -- check before committing.
++ Make sure you have added the necessary tests for your changes, typically in `src/test/java`.
++ Run all the tests with `mvn clean verify` to assure nothing else was accidentally broken.
+
+Making Trivial Changes
+----------------------
+
+The JIRA tickets are used to generate the changelog for the next release.
+
+For changes of a trivial nature to comments and documentation, it is not always necessary to create a new ticket in JIRA.
+In this case, it is appropriate to start the first line of a commit with '(doc)' instead of a ticket number.
+
+
+Submitting Changes
+------------------
+
++ Sign and submit the Apache [Contributor License Agreement][cla] if you haven't already.
+  * Note that small patches & typical bug fixes do not require a CLA as
+    clause 5 of the [Apache License](https://www.apache.org/licenses/LICENSE-2.0.html#contributions)
+    covers them.
++ Push your changes to a topic branch in your fork of the repository.
++ Submit a _Pull Request_ to the corresponding repository in the `apache` organization.
+  * Verify _Files Changed_ shows only your intended changes and does not
+  include additional files like `target/*.class`
++ Update your JIRA ticket and include a link to the pull request in the ticket.
+
+If you prefer to not use GitHub, then you can instead use
+`git format-patch` (or `svn diff`) and attach the patch file to the JIRA issue.
+
+
+Additional Resources
+--------------------
+
++ [Contributing patches](https://commons.apache.org/patches.html)
++ [Apache Commons Validator JIRA project page][jira]
++ [Contributor License Agreement][cla]
++ [General GitHub documentation](https://help.github.com/)
++ [GitHub pull request documentation](https://help.github.com/articles/creating-a-pull-request/)
++ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)
++ `#apache-commons` IRC channel on `irc.freenode.net`
+
+[cla]:https://www.apache.org/licenses/#clas
+[jira]:https://issues.apache.org/jira/browse/VALIDATOR
diff --git a/NOTICE.txt b/NOTICE.txt
index 489eee6..273b9df 100644
--- a/NOTICE.txt
+++ b/NOTICE.txt
@@ -1,5 +1,5 @@
 Apache Commons Validator
-Copyright 2001-2023 The Apache Software Foundation
+Copyright 2002-2024 The Apache Software Foundation
 
 This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
+The Apache Software Foundation (https://www.apache.org/).
diff --git a/README.md b/README.md
index 68a971a..906dbdd 100644
--- a/README.md
+++ b/README.md
@@ -1,107 +1,120 @@
-<!---

- Licensed to the Apache Software Foundation (ASF) under one or more

- contributor license agreements.  See the NOTICE file distributed with

- this work for additional information regarding copyright ownership.

- The ASF licenses this file to You under the Apache License, Version 2.0

- (the "License"); you may not use this file except in compliance with

- the License.  You may obtain a copy of the License at

-

-      http://www.apache.org/licenses/LICENSE-2.0

-

- Unless required by applicable law or agreed to in writing, software

- distributed under the License is distributed on an "AS IS" BASIS,

- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

- See the License for the specific language governing permissions and

- limitations under the License.

--->

-<!---

- +======================================================================+

- |****                                                              ****|

- |****      THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN      ****|

- |****                    DO NOT EDIT DIRECTLY                      ****|

- |****                                                              ****|

- +======================================================================+

- | TEMPLATE FILE: readme-md-template.md                                 |

- | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |

- +======================================================================+

- |                                                                      |

- | 1) Re-generate using: mvn commons-build:readme-md                    |

- |                                                                      |

- | 2) Set the following properties in the component's pom:              |

- |    - commons.componentid (required, alphabetic, lower case)          |

- |    - commons.release.version (required)                              |

- |                                                                      |

- | 3) Example Properties                                                |

- |                                                                      |

- |  <properties>                                                        |

- |    <commons.componentid>math</commons.componentid>                   |

- |    <commons.release.version>1.2</commons.release.version>            |

- |  </properties>                                                       |

- |                                                                      |

- +======================================================================+

---->

-Apache Commons Validator

-===================

-

-[![GitHub Actions Status](https://github.com/apache/commons-validator/workflows/Java%20CI/badge.svg)](https://github.com/apache/commons-validator/actions)

-[![Coverage Status](https://codecov.io/gh/apache/commons-validator/branch/master/graph/badge.svg)](https://app.codecov.io/gh/apache/commons-validator)

-[![Maven Central](https://maven-badges.herokuapp.com/maven-central/commons-validator/commons-validator/badge.svg?gav=true)](https://maven-badges.herokuapp.com/maven-central/commons-validator/commons-validator/?gav=true)

-[![Javadocs](https://javadoc.io/badge/commons-validator/commons-validator/1.7.svg)](https://javadoc.io/doc/commons-validator/commons-validator/1.7)

-[![CodeQL](https://github.com/apache/commons-validator/workflows/CodeQL/badge.svg)](https://github.com/apache/commons-validator/actions/workflows/codeql-analysis.yml?query=workflow%3ACodeQL)

-

-Apache Commons Validator provides the building blocks for both client side validation and server side data validation.

-    It may be used standalone or with a framework like Struts.

-

-Documentation

--------------

-

-More information can be found on the [Apache Commons Validator homepage](https://commons.apache.org/proper/commons-validator).

-The [Javadoc](https://commons.apache.org/proper/commons-validator/apidocs) can be browsed.

-Questions related to the usage of Apache Commons Validator should be posted to the [user mailing list][ml].

-

-Where can I get the latest release?

------------------------------------

-You can download source and binaries from our [download page](https://commons.apache.org/proper/commons-validator/download_validator.cgi).

-

-Alternatively you can pull it from the central Maven repositories:

-

-```xml

-<dependency>

-  <groupId>commons-validator</groupId>

-  <artifactId>commons-validator</artifactId>

-  <version>1.7</version>

-</dependency>

-```

-

-Contributing

-------------

-

-We accept Pull Requests via GitHub. The [developer mailing list][ml] is the main channel of communication for contributors.

-There are some guidelines which will make applying PRs easier for us:

-+ No tabs! Please use spaces for indentation.

-+ Respect the code style.

-+ Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change.

-+ Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running ```mvn```.

-

-If you plan to contribute on a regular basis, please consider filing a [contributor license agreement](https://www.apache.org/licenses/#clas).

-You can learn more about contributing via GitHub in our [contribution guidelines](CONTRIBUTING.md).

-

-License

--------

-This code is under the [Apache Licence v2](https://www.apache.org/licenses/LICENSE-2.0).

-

-See the `NOTICE.txt` file for required notices and attributions.

-

-Donations

----------

-You like Apache Commons Validator? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support the development.

-

-Additional Resources

---------------------

-

-+ [Apache Commons Homepage](https://commons.apache.org/)

-+ [Apache Issue Tracker (JIRA)](https://issues.apache.org/jira/browse/VALIDATOR)

-+ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)

-+ `#apache-commons` IRC channel on `irc.freenode.org`

-

-[ml]:https://commons.apache.org/mail-lists.html

+<!---
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements.  See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<!---
+ +======================================================================+
+ |****                                                              ****|
+ |****      THIS FILE IS GENERATED BY THE COMMONS BUILD PLUGIN      ****|
+ |****                    DO NOT EDIT DIRECTLY                      ****|
+ |****                                                              ****|
+ +======================================================================+
+ | TEMPLATE FILE: readme-md-template.md                                 |
+ | commons-build-plugin/trunk/src/main/resources/commons-xdoc-templates |
+ +======================================================================+
+ |                                                                      |
+ | 1) Re-generate using: mvn commons-build:readme-md                    |
+ |                                                                      |
+ | 2) Set the following properties in the component's pom:              |
+ |    - commons.componentid (required, alphabetic, lower case)          |
+ |    - commons.release.version (required)                              |
+ |                                                                      |
+ | 3) Example Properties                                                |
+ |                                                                      |
+ |  <properties>                                                        |
+ |    <commons.componentid>math</commons.componentid>                   |
+ |    <commons.release.version>1.2</commons.release.version>            |
+ |  </properties>                                                       |
+ |                                                                      |
+ +======================================================================+
+--->
+Apache Commons Validator
+===================
+
+[![Java CI](https://github.com/apache/commons-validator/actions/workflows/maven.yml/badge.svg)](https://github.com/apache/commons-validator/actions/workflows/maven.yml)
+[![Coverage Status](https://codecov.io/gh/apache/commons-validator/branch/master/graph/badge.svg)](https://app.codecov.io/gh/apache/commons-validator)
+[![Maven Central](https://maven-badges.herokuapp.com/maven-central/commons-validator/commons-validator/badge.svg?gav=true)](https://maven-badges.herokuapp.com/maven-central/commons-validator/commons-validator/?gav=true)
+[![Javadocs](https://javadoc.io/badge/commons-validator/commons-validator/1.8.0.svg)](https://javadoc.io/doc/commons-validator/commons-validator/1.8.0)
+[![CodeQL](https://github.com/apache/commons-validator/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/apache/commons-validator/actions/workflows/codeql-analysis.yml)
+[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/commons-validator/badge)](https://api.securityscorecards.dev/projects/github.com/apache/commons-validator)
+
+Apache Commons Validator provides the building blocks for both client side validation and server side data validation.
+    It may be used standalone or with a framework like Struts.
+
+Documentation
+-------------
+
+More information can be found on the [Apache Commons Validator homepage](https://commons.apache.org/proper/commons-validator).
+The [Javadoc](https://commons.apache.org/proper/commons-validator/apidocs) can be browsed.
+Questions related to the usage of Apache Commons Validator should be posted to the [user mailing list](https://commons.apache.org/mail-lists.html).
+
+Getting the latest release
+--------------------------
+You can download source and binaries from our [download page](https://commons.apache.org/proper/commons-validator/download_validator.cgi).
+
+Alternatively, you can pull it from  the central Maven repositories:
+
+```xml
+<dependency>
+  <groupId>commons-validator</groupId>
+  <artifactId>commons-validator</artifactId>
+  <version>1.8.0</version>
+</dependency>
+```
+
+Building
+--------
+
+Building requires a Java JDK and [Apache Maven](https://maven.apache.org/). 
+The required Java version is found in the `pom.xml` as the `maven.compiler.source` property.
+
+From a command shell, run `mvn` without arguments to invoke the default Maven goal to run all tests and checks.
+
+Contributing
+------------
+
+We accept Pull Requests via GitHub. The [developer mailing list](https://commons.apache.org/mail-lists.html) is the main channel of communication for contributors.
+There are some guidelines which will make applying PRs easier for us:
++ No tabs! Please use spaces for indentation.
++ Respect the existing code style for each file.
++ Create minimal diffs - disable on save actions like reformat source code or organize imports. If you feel the source code should be reformatted create a separate PR for this change.
++ Provide JUnit tests for your changes and make sure your changes don't break any existing tests by running ```mvn```.
+
+If you plan to contribute on a regular basis, please consider filing a [contributor license agreement](https://www.apache.org/licenses/#clas).
+You can learn more about contributing via GitHub in our [contribution guidelines](CONTRIBUTING.md).
+
+License
+-------
+This code is licensed under the [Apache License v2](https://www.apache.org/licenses/LICENSE-2.0).
+
+See the `NOTICE.txt` file for required notices and attributions.
+
+Donating
+--------
+You like Apache Commons Validator? Then [donate back to the ASF](https://www.apache.org/foundation/contributing.html) to support development.
+
+Additional Resources
+--------------------
+
++ [Apache Commons Homepage](https://commons.apache.org/)
++ [Apache Issue Tracker (JIRA)](https://issues.apache.org/jira/browse/VALIDATOR)
++ [Apache Commons Slack Channel](https://the-asf.slack.com/archives/C60NVB8AD)
++ [Apache Commons Twitter Account](https://twitter.com/ApacheCommons)
++ `#apache-commons` IRC channel on `irc.freenode.org`
+
+Apache Commons Components
+-------------------------
+
+Please see the [list of components](https://commons.apache.org/components.html)
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 395eeb1..2e30588 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -1,5 +1,80 @@
-              Apache Commons Validator 1.7
-                  RELEASE NOTES
+Apache Commons Validator 1.8.0
+RELEASE NOTES
+
+The Apache Commons Validator team is pleased to announce the release of Apache Commons Validator 1.8.0.
+
+Apache Commons Validator provides the building blocks for both client side validation and server side data validation.
+It may be used standalone or with a framework like Struts.
+
+For complete information on Apache Commons Validator, including instructions on how to submit bug reports,
+patches, or suggestions for improvement, see the Apache Commons Validator website:
+
+http://commons.apache.org/proper/commons-validator/
+
+Download page: http://commons.apache.org/proper/commons-validator/download_validator.cgi
+
+Changes in this version
+-----------------------
+
+New features
+------------
+
+*                 Add github/codeql-action. Thanks to Dependabot, Gary Gregory.
+* VALIDATOR-486:  Add new countries to IBAN list: DJ, RU #88. Thanks to tatiana-scda, Gary Gregory.
+*                 Add IBANValidator.Validator.getRegexValidator(). Thanks to Arnaud Fournier, Gary Gregory.
+*                 Add RegexValidator.getPatterns(). Thanks to Arnaud Fournier, Gary Gregory.
+*                 Add country codes listed as other countries and territories in the IBAN registry for Finland: AX. Thanks to Gary Gregory, rossmills3, sebbASF.
+*                 Add country codes listed as other countries and territories in the IBAN registry for France: GF, GP, MQ, RE, PF, TF, YT, NC, BL, MF, PM, WF. Thanks to Gary Gregory, rossmills3, sebbASF.
+*                 Add country codes listed as other countries and territories in the IBAN registry for United Kingdom: IM, JE, GG. Thanks to Gary Gregory, rossmills3, sebbASF.
+*                 Add ValidatorAction.setClassName(String) and deprecate setClassname(String). Thanks to Gary Gregory.
+
+Fixed Bugs
+----------
+
+*                 Update Javadoc for InetAddressValidator isValid #76 Thanks to Gennaro Napolitano.
+* VALIDATOR-479:  Fix typo in /routines/package-summary.html #79. Thanks to Gyoo.
+*                 Use JUnit 5 assertThrows() #92, #93, #94, #95. Thanks to John Patrick.
+*                 [StepSecurity] ci: Harden GitHub Actions #136. Thanks to step-security-bot, Gary Gregory.
+*                 Javadoc typos #144. Thanks to Andrés Torres.
+*                 Precompile regular expression in InetAddressValidator.isValidInet6Address(String). Thanks to Gary Gregory.
+*                 Fix SpotBugs [ERROR] Medium: Class org.apache.commons.validator.routines.CreditCardValidator$1 defines non-transient non-serializable instance field ccr [org.apache.commons.validator.routines.CreditCardValidator$1] In CreditCardValidator.java SE_BAD_FIELD. Thanks to Gary Gregory.
+*                 Fix SpotBugs [ERROR] High: Class org.apache.commons.validator.ValidatorAction defines non-transient non-serializable instance field validationMethod [org.apache.commons.validator.ValidatorAction] In ValidatorAction.java SE_BAD_FIELD. Thanks to Gary Gregory.
+*                 Fix SpotBugs [ERROR] High: Found reliance on default encoding in org.apache.commons.validator.ValidatorAction.readJavascriptFile(String): new java.io.InputStreamReader(InputStream) [org.apache.commons.validator.ValidatorAction] At ValidatorAction.java:[line 428] DM_DEFAULT_ENCODING. Thanks to Gary Gregory.
+*                 Fix SpotBugs [ERROR] Medium: Inconsistent synchronization of org.apache.commons.validator.ValidatorAction.jsFunction; locked 62% of time [org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction] Unsynchronized access at ValidatorAction.java:[line 340]Unsynchronized access at ValidatorAction.java:[line 358]Synchronized access at ValidatorAction.java:[line 393]Synchronized access at ValidatorAction.java:[line 394]Synchronized access at ValidatorAction.java:[line 459]Synchronized access at ValidatorAction.java:[line 461]Synchronized access at ValidatorAction.java:[line 462] IS2_INCONSISTENT_SYNC. Thanks to Gary Gregory.
+*                 Port tests to JUnit 5. Exception: DomainValidatorStartupTest. Thanks to Gary Gregory.
+*                 Use singletons in org.apache.commons.validator.CreditCardValidator. Thanks to Gary Gregory.
+
+Changes
+-------
+
+*                 Bump Java from 7 to 8. Thanks to Gary Gregory.
+*                 Bump actions/cache from 2 to 3.0.11 #71, #84. #90, #91. Thanks to Dependabot, Gary Gregory.
+*                 Bump actions/checkout from 2.3.1 to 3.0.2, #38, #47, #70. Thanks to Dependabot, Gary Gregory.
+*                 Bump actions/setup-java from 1.4.0 to 3.6.0 #42, #72, #98. Thanks to Dependabot, Gary Gregory.
+*                 Bump actions/upload-artifact from 3.1.0 to 3.1.1 #96. Thanks to Dependabot.
+*                 Bump junit from 4.13 to 5.9.1 Vintage #44. Thanks to Dependabot, Gary Gregory.
+*                 Bump maven-pmd-plugin from 3.13.0 to 3.19.0 #69, #77, #80, #81. Thanks to Dependabot.
+*                 Bump commons-parent from 52 to 65 #83, #107, #111, #132. Thanks to Gary Gregory, Dependabot.
+*                 Bump japicmp-maven-plugin from 0.15.3 to 0.15.7. Thanks to Gary Gregory.
+*                 Bump maven-antrun-plugin from 3.0.0 to 3.1.0 #74. Thanks to Dependabot.
+*                 Bump commons-csv from 1.6 to 1.10.0 #118. Thanks to Gary Gregory, Dependabot.
+*                 Bump japicmp-maven-plugin from 0.15.7 to 0.16.0. Thanks to Gary Gregory.
+*                 Bump commons-logging:commons-logging from 1.2 to 1.3.0. Thanks to Gary Gregory.
+
+Removed
+-------
+
+*                 Remove FindBugs, SpotBugs is in use #87. Thanks to John Patrick, Gary Gregory.
+
+Historical list of changes: http://commons.apache.org/proper/commons-validator/changes-report.html
+
+Enjoy!
+-Apache Commons Validator team
+
+-----------------------------------------------------------------------------
+
+Apache Commons Validator 1.7
+RELEASE NOTES
 
 The Apache Commons Validator team is pleased to announce the release of Apache Commons Validator 1.7
 
@@ -13,14 +88,14 @@
 Commons Validator requires Java 7 or later.
 
 Main enhancements
-=================
+-----------------
 
 * CreditCard validation specification by numeric range
 * DomainValidator instances can be created with instance overrides
 * DomainValidator supports overrides of LOCAL TLDs
 
 IMPORTANT NOTES
-===============
+---------------
 
 BREAKING CHANGES:
 
@@ -28,7 +103,7 @@
 * N.B. Java 9 changed the way Locales are handled. This affects the output from some Date-related methods, and may cause some tests to break.
 
 DEPENDENCIES
-============
+------------
 
 * Updates Apache Commons BeanUtils dependency from 1.9.2 to 1.9.4.
  This picks up BEANUTILS-482: Update commons-collections from 3.2.1 to 3.2.2 (CVE-2015-4852).
@@ -42,47 +117,55 @@
 
 Download page: http://commons.apache.org/proper/commons-validator/download_validator.cgi
 
-Changes in this version include:
-===============================
+Changes in this version
+-----------------------
 
-New features:
-o VALIDATOR-474:  DomainValidator should allow local overrides
-o VALIDATOR-473:  Allow Email- and UrlValidator to use specified DomainValidator
-o VALIDATOR-471:  Allow DomainValidator overrides at run-time
-o VALIDATOR-423:  Add ISINValidator
-o VALIDATOR-455:  Add IBAN validator for VA – Vatican City State Thanks to Eugen Hanussek.
-o VALIDATOR-446:  ISSN Validator extract ISSN from EAN-13 Thanks to Alex.
+New features
+------------
 
-Fixed Bugs:
-o VALIDATOR-403:  Accept Discover cards of 17 digits long that start with 6011 Thanks to Tanya.
-o VALIDATOR-408:  DISCOVER Card Validation Patterns Thanks to Raj Vaida.
-o VALIDATOR-472:  UrlValidator should not be more lax than java.net.URI
-o VALIDATOR-283:  URLValidator should check for illegal Hex characters Thanks to RC Johnson.
-o VALIDATOR-445:  Inet6Address may also contain a scope id Thanks to devson.
-o VALIDATOR-452:  Validation of URL containing IPv4-mapped IPv6 address Thanks to devson.
-o VALIDATOR-438:  IBANValidator fails for El Salvador
+* VALIDATOR-474:  DomainValidator should allow local overrides
+* VALIDATOR-473:  Allow Email- and UrlValidator to use specified DomainValidator
+* VALIDATOR-471:  Allow DomainValidator overrides at run-time
+* VALIDATOR-423:  Add ISINValidator
+* VALIDATOR-455:  Add IBAN validator for VA – Vatican City State Thanks to Eugen Hanussek.
+* VALIDATOR-446:  ISSN Validator extract ISSN from EAN-13 Thanks to Alex.
+
+Fixed Bugs
+----------
+
+* VALIDATOR-403:  Accept Discover cards of 17 digits long that start with 6011 Thanks to Tanya.
+* VALIDATOR-408:  DISCOVER Card Validation Patterns Thanks to Raj Vaida.
+* VALIDATOR-472:  UrlValidator should not be more lax than java.net.URI
+* VALIDATOR-283:  URLValidator should check for illegal Hex characters Thanks to RC Johnson.
+* VALIDATOR-445:  Inet6Address may also contain a scope id Thanks to devson.
+* VALIDATOR-452:  Validation of URL containing IPv4-mapped IPv6 address Thanks to devson.
+* VALIDATOR-438:  IBANValidator fails for El Salvador
                   Add definition Thanks to Simon Marti.
-o VALIDATOR-434:  Field does not synchronize iteration on synchronized list Thanks to emopers.
-o VALIDATOR-437:  Update Apache Commons BeanUtils dependency from 1.9.2 to 1.9.3.
+* VALIDATOR-434:  Field does not synchronize iteration on synchronized list Thanks to emopers.
+* VALIDATOR-437:  Update Apache Commons BeanUtils dependency from 1.9.2 to 1.9.3.
                   This picks up BEANUTILS-482: Update commons-collections from 3.2.1 to 3.2.2 (CVE-2015-4852).
-o VALIDATOR-460:  Update Apache Commons BeanUtils dependency from 1.9.3 to 1.9.4
+* VALIDATOR-460:  Update Apache Commons BeanUtils dependency from 1.9.3 to 1.9.4
                   This picks up BEANUTILS-520: Mitigate CVE-2014-0114. Thanks to Jeff Schram.
-o VALIDATOR-461:  Generic .gmbh top level domain is considered invalid Thanks to Nils Reischmann.
-o VALIDATOR-444:  LongValidator: numbers bigger than the maxvalue are Valid Thanks to Martin Scholz.
-o VALIDATOR-416:  CreditCardValidator default ctor disagrees with Javadoc
-o VALIDATOR-467:  URL validator fails if path starts with double slash and has underscores Thanks to Ivan Larionov.
-o VALIDATOR-464:  UrlValidator says "file://bad ^ domain.com/label/test" is valid Thanks to Sebastian Choina.
-o VALIDATOR-449:  Leading and trailing spaces in EmailValidator should not be valid Thanks to Frederic Boutin.
-o VALIDATOR-302:  EMailValidator: Addresses with leading spaces must not be accepted Thanks to Guido Zockoll.
-o VALIDATOR-468:  DomainValidator.getTLDArray does not synch mutable arrays
+* VALIDATOR-461:  Generic .gmbh top level domain is considered invalid Thanks to Nils Reischmann.
+* VALIDATOR-444:  LongValidator: numbers bigger than the maxvalue are Valid Thanks to Martin Scholz.
+* VALIDATOR-416:  CreditCardValidator default ctor disagrees with Javadoc
+* VALIDATOR-467:  URL validator fails if path starts with double slash and has underscores Thanks to Ivan Larionov.
+* VALIDATOR-464:  UrlValidator says "file://bad ^ domain.com/label/test" is valid Thanks to Sebastian Choina.
+* VALIDATOR-449:  Leading and trailing spaces in EmailValidator should not be valid Thanks to Frederic Boutin.
+* VALIDATOR-302:  EMailValidator: Addresses with leading spaces must not be accepted Thanks to Guido Zockoll.
+* VALIDATOR-468:  DomainValidator.getTLDArray does not synch mutable arrays
 
-Changes:
-o                 Drop Clirr and Cobertura in favour of JApiCmp and JaCoCo
-o                 IANA TLD lists: Updated to Version 2020073100, Last Updated Fri Jul 31 07:07:01 2020 UTC
-o VALIDATOR-428:  Update commons digester to 2.1 Thanks to Matthew Zavislak.
+Changes
+-------
+
+*                 Drop Clirr and Cobertura in favour of JApiCmp and JaCoCo
+*                 IANA TLD lists: Updated to Version 2020073100, Last Updated Fri Jul 31 07:07:01 2020 UTC
+* VALIDATOR-428:  Update commons digester to 2.1 Thanks to Matthew Zavislak.
 
 
 Historical list of changes: http://commons.apache.org/proper/commons-validator/changes-report.html
 
 Enjoy!
--Apache Commons Validator team
+- The Apache Commons Validator team
+
+-----------------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index be62859..a7c311c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -22,12 +22,12 @@
   <parent>

     <groupId>org.apache.commons</groupId>

     <artifactId>commons-parent</artifactId>

-    <version>56</version>

+    <version>67</version>

   </parent>

 

   <groupId>commons-validator</groupId>

   <artifactId>commons-validator</artifactId>

-  <version>1.8-SNAPSHOT</version>

+  <version>1.8.1-SNAPSHOT</version>

   <name>Apache Commons Validator</name>

   <description>

     Apache Commons Validator provides the building blocks for both client side validation and server side data validation.

@@ -40,10 +40,11 @@
     <commons.componentid>validator</commons.componentid>

     <commons.module.name>org.apache.commons.validator</commons.module.name>

     <!-- Re-generate the download page using: mvn commons:download-page -->

-    <commons.release.version>1.7</commons.release.version>

-    <commons.rc.version>RC2</commons.rc.version>

+    <commons.release.version>1.8.0</commons.release.version>

+    <commons.release.next>1.8.1</commons.release.next>

+    <commons.rc.version>RC1</commons.rc.version>

     <commons.release.desc>(requires JDK ${maven.compiler.target})</commons.release.desc>

-    <commons.bc.version>1.6</commons.bc.version>

+    <commons.bc.version>1.7</commons.bc.version>

     <commons.jira.id>VALIDATOR</commons.jira.id>

     <commons.jira.pid>12310494</commons.jira.pid>

     <commons.encoding>UTF-8</commons.encoding>

@@ -55,6 +56,7 @@
     <maven.compiler.target>1.8</maven.compiler.target>

     <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

     <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

+    <project.build.outputTimestamp>2024-01-01T00:00:00Z</project.build.outputTimestamp>

     <commons.release.isDistModule>true</commons.release.isDistModule>

   </properties> 

 

@@ -78,7 +80,20 @@
   </distributionManagement>

 

   <build>

-    <defaultGoal>clean verify apache-rat:check japicmp:cmp checkstyle:check javadoc:javadoc</defaultGoal>

+    <defaultGoal>clean verify apache-rat:check japicmp:cmp checkstyle:check spotbugs:check javadoc:javadoc</defaultGoal>

+    <pluginManagement>

+      <plugins>

+        <plugin>

+          <groupId>com.github.spotbugs</groupId>

+          <artifactId>spotbugs-maven-plugin</artifactId>

+          <configuration>

+            <threshold>Normal</threshold>

+            <effort>Default</effort>

+            <excludeFilterFile>${basedir}/src/conf/spotbugs-exclude-filter.xml</excludeFilterFile>

+         </configuration>

+        </plugin>

+      </plugins>

+	</pluginManagement>

     <resources>

       <resource>

         <directory>${basedir}</directory>

@@ -117,6 +132,7 @@
         <artifactId>maven-checkstyle-plugin</artifactId>

         <configuration>

           <configLocation>${basedir}/src/conf/checkstyle.xml</configLocation>

+          <!-- TODO <includeTestSourceDirectory>true</includeTestSourceDirectory> -->

           <!-- Needed to define config_loc -->

           <propertyExpansion>config_loc=${basedir}/src/conf</propertyExpansion>

           <enableRulesSummary>false</enableRulesSummary>

@@ -157,7 +173,7 @@
     <dependency>

       <groupId>commons-logging</groupId>

       <artifactId>commons-logging</artifactId>

-      <version>1.2</version>

+      <version>1.3.0</version>

     </dependency>

 

     <dependency>

@@ -179,6 +195,11 @@
       <artifactId>junit-vintage-engine</artifactId>

       <scope>test</scope>

     </dependency>

+    <dependency>

+      <groupId>org.junit.jupiter</groupId>

+      <artifactId>junit-jupiter</artifactId>

+      <scope>test</scope>

+    </dependency>

 

     <dependency>

       <!-- For testing DomainValidatorStartup -->

@@ -232,6 +253,10 @@
           </excludes>

         </configuration>

       </plugin>

+      <plugin>

+        <groupId>com.github.spotbugs</groupId>

+        <artifactId>spotbugs-maven-plugin</artifactId>

+      </plugin>

     </plugins>

   </reporting>

 

diff --git a/src/assembly/bin.xml b/src/assembly/bin.xml
index b57a513..9a18965 100644
--- a/src/assembly/bin.xml
+++ b/src/assembly/bin.xml
@@ -14,7 +14,9 @@
  See the License for the specific language governing permissions and
  limitations under the License.
 -->
-<assembly>
+<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd">
     <id>bin</id>
     <formats>
         <format>tar.gz</format>
diff --git a/src/assembly/src.xml b/src/assembly/src.xml
index 04a4b96..f842f63 100644
--- a/src/assembly/src.xml
+++ b/src/assembly/src.xml
@@ -14,7 +14,9 @@
  See the License for the specific language governing permissions and
  limitations under the License.
 -->
-<assembly>
+<assembly xmlns="http://maven.apache.org/ASSEMBLY/2.2.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/ASSEMBLY/2.2.0 http://maven.apache.org/xsd/assembly-2.2.0.xsd">
     <id>src</id>
     <formats>
         <format>tar.gz</format>
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 7b83991..1a6409a 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -64,7 +64,13 @@
      -->

 

   <body>

-  <release version="1.8" date="20YY-MM-DD" description="">

+  <release version="1.8.1" date="202Y-MM-DD" description="Maintenance and bug fix release.">

+    <!-- FIX -->

+    <action type="fix" issue="VALIDATOR-492" dev="ggregory" due-to="Tobias Wildgruber, Gary Gregory">ValidatorUtils.copyFastHashMap is broken.</action>

+    <!-- UPDATE -->

+    <action type="update" dev="ggregory" due-to="Dependabot">Bump org.apache.commons:commons-parent from 65 to 67.</action>

+  </release>

+  <release version="1.8.0" date="2023-12-02" description="Maintenance and bug fix release.">

     <!-- FIX -->

     <action type="fix" dev="ggregory" due-to="Gennaro Napolitano">

       Update Javadoc for InetAddressValidator isValid #76

@@ -75,6 +81,33 @@
     <action type="fix" dev="ggregory" due-to="John Patrick">

       Use JUnit 5 assertThrows() #92, #93, #94, #95.

     </action>

+    <action type="fix" dev="ggregory" due-to="step-security-bot, Gary Gregory">

+      [StepSecurity] ci: Harden GitHub Actions #136.

+    </action>

+    <action type="fix" dev="ggregory" due-to="Andrés Torres">

+      Javadoc typos #144.

+    </action>

+    <action type="fix" dev="ggregory" due-to="Gary Gregory">

+      Precompile regular expression in InetAddressValidator.isValidInet6Address(String).

+    </action>

+    <action type="fix" dev="ggregory" due-to="Gary Gregory">

+      Fix SpotBugs [ERROR] Medium: Class org.apache.commons.validator.routines.CreditCardValidator$1 defines non-transient non-serializable instance field ccr [org.apache.commons.validator.routines.CreditCardValidator$1] In CreditCardValidator.java SE_BAD_FIELD.

+    </action>

+    <action type="fix" dev="ggregory" due-to="Gary Gregory">

+      Fix SpotBugs [ERROR] High: Class org.apache.commons.validator.ValidatorAction defines non-transient non-serializable instance field validationMethod [org.apache.commons.validator.ValidatorAction] In ValidatorAction.java SE_BAD_FIELD.

+    </action>

+    <action type="fix" dev="ggregory" due-to="Gary Gregory">

+      Fix SpotBugs [ERROR] High: Found reliance on default encoding in org.apache.commons.validator.ValidatorAction.readJavascriptFile(String): new java.io.InputStreamReader(InputStream) [org.apache.commons.validator.ValidatorAction] At ValidatorAction.java:[line 428] DM_DEFAULT_ENCODING.

+    </action>

+    <action type="fix" dev="ggregory" due-to="Gary Gregory">

+      Fix SpotBugs [ERROR] Medium: Inconsistent synchronization of org.apache.commons.validator.ValidatorAction.jsFunction; locked 62% of time [org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction, org.apache.commons.validator.ValidatorAction] Unsynchronized access at ValidatorAction.java:[line 340]Unsynchronized access at ValidatorAction.java:[line 358]Synchronized access at ValidatorAction.java:[line 393]Synchronized access at ValidatorAction.java:[line 394]Synchronized access at ValidatorAction.java:[line 459]Synchronized access at ValidatorAction.java:[line 461]Synchronized access at ValidatorAction.java:[line 462] IS2_INCONSISTENT_SYNC.

+    </action>

+    <action type="fix" dev="ggregory" due-to="Gary Gregory">

+      Port tests to JUnit 5. Exception: DomainValidatorStartupTest.

+    </action>

+    <action type="fix" dev="ggregory" due-to="Gary Gregory">

+      Use singletons in org.apache.commons.validator.CreditCardValidator.

+    </action>

     <!-- ADD -->

     <action type="add" dev="ggregory" due-to="Dependabot, Gary Gregory">

       Add github/codeql-action.

@@ -100,6 +133,9 @@
     <action type="add" dev="ggregory" due-to="Gary Gregory, rossmills3, sebbASF">

       Add country codes listed as other countries and territories in the IBAN registry for United Kingdom: IM, JE, GG.

     </action>

+    <action type="add" dev="ggregory" due-to="Gary Gregory">

+      Add ValidatorAction.setClassName(String) and deprecate setClassname(String). 

+    </action>

     <!-- REMOVE -->

     <action type="remove" dev="ggregory" due-to="John Patrick, Gary Gregory">

       Remove FindBugs, SpotBugs is in use #87.

@@ -127,7 +163,7 @@
       Bump maven-pmd-plugin from 3.13.0 to 3.19.0 #69, #77, #80, #81.

     </action>

     <action type="update" dev="ggregory" due-to="Gary Gregory, Dependabot">

-      Bump commons-parent from 52 to 56, #83, #107, #111.

+      Bump commons-parent from 52 to 65 #83, #107, #111, #132.

     </action>

     <action type="update" dev="ggregory" due-to="Gary Gregory">

       Bump japicmp-maven-plugin from 0.15.3 to 0.15.7.

@@ -141,6 +177,9 @@
     <action type="update" dev="ggregory" due-to="Gary Gregory">

       Bump japicmp-maven-plugin from 0.15.7 to 0.16.0.

     </action>

+    <action dev="ggregory" type="update" due-to="Gary Gregory">

+      Bump commons-logging:commons-logging from 1.2 to 1.3.0.

+    </action>

   </release>

   

   <release version="1.7" date="2020-08-07" description="

diff --git a/src/changes/release-notes.vm b/src/changes/release-notes.vm
index ab20c18..9f9b498 100644
--- a/src/changes/release-notes.vm
+++ b/src/changes/release-notes.vm
@@ -15,10 +15,10 @@
 ## specific language governing permissions and limitations
 ## under the License.
 ##
-              ${project.name} ${version}
-                  RELEASE NOTES
+${project.name} ${version}
+RELEASE NOTES
 
-The ${developmentTeam} is pleased to announce the release of ${project.name} ${version}
+The ${developmentTeam} is pleased to announce the release of ${project.name} ${version}.
 
 $introduction.replaceAll("(?<!\015)\012", "
 ").replaceAll("(?m)^ +","")
@@ -77,7 +77,7 @@
 #else
 #set($dueto="")
 #end
-o $issue ${action}$dueto
+* $issue ${action}$dueto
 #end
 #set($action="")
 #set($issue="")
@@ -87,11 +87,13 @@
 #if ($release.getActions().size() == 0)
 No changes defined in this version.
 #else
-Changes in this version include:
-===============================
+Changes in this version
+-----------------------
 
 #if ($release.getActions('add').size() !=0)
-New features:
+New features
+------------
+
 #foreach($actionItem in $release.getActions('add'))
 #processaction()
 #end 
@@ -99,7 +101,9 @@
 #end
 ##
 #if ($release.getActions('fix').size() !=0)
-Fixed Bugs:
+Fixed Bugs
+----------
+
 #foreach($actionItem in $release.getActions('fix'))
 #processaction()
 #end
@@ -107,7 +111,9 @@
 #end
 ##
 #if ($release.getActions('update').size() !=0)
-Changes:
+Changes
+-------
+
 #foreach($actionItem in $release.getActions('update'))
 #processaction()
 #end
@@ -115,7 +121,9 @@
 #end
 ##
 #if ($release.getActions('remove').size() !=0)
-Removed:
+Removed
+-------
+
 #foreach($actionItem in $release.getActions('remove'))
 #processaction()
 #end
@@ -127,3 +135,5 @@
 
 Enjoy!
 -Apache Commons Validator team
+
+-----------------------------------------------------------------------------
diff --git a/src/conf/checkstyle.xml b/src/conf/checkstyle.xml
index 5958cb9..fc2c599 100644
--- a/src/conf/checkstyle.xml
+++ b/src/conf/checkstyle.xml
@@ -16,10 +16,8 @@
  limitations under the License.
 -->
 <!DOCTYPE module PUBLIC
-    "-//Checkstyle//DTD Checkstyle Configuration 1.2//EN"
-    "https://checkstyle.org/dtds/configuration_1_2.dtd">
-
-
+    "-//Checkstyle//DTD Checkstyle Configuration 1.3//EN"
+    "https://checkstyle.org/dtds/configuration_1_3.dtd">
 <!--
   
   These checks still need to be Voted on for Validator, but
@@ -38,44 +36,34 @@
   is a high priority goal for the development team.
 
 -->
-
 <module name="Checker">
 
-   <module name="TreeWalker">
+  <module name="TreeWalker">
 
     <!-- Item 4 - Avoid creating duplicate objects -->
     <module name="IllegalInstantiation">
-      <property name="classes" value="java.lang.Boolean, java.lang.String"/>
+      <property name="classes" value="java.lang.Boolean, java.lang.String" />
     </module>
 
     <!-- Item 8 - Always override hashCode when you override equals -->
-    <module name="EqualsHashCode"/>
+    <module name="EqualsHashCode" />
 
     <!-- Item 12 - Make all fields private -->
-    <!--
-    <module name="VisibilityModifier"/>
-    -->
+    <!-- <module name="VisibilityModifier"/> -->
 
     <!-- Item 15 - Design and document for inheritance or else prohibit it -->
-    <!-- the module actually implements a very strict rule, it would be
-         interesting to know whether Joshua meant what checkstyle implements.
-         We feel this implementation is well suited as a warning,
-         i.e. if you get error messages from this check you should be
-         able to name a good reason to implement your code the way you do it,
-         especially if you are designing a library and not an application. -->
-    <!--
-    <module name="DesignForExtension">
-      <property name="severity" value="warning"/>
-    </module>
-    -->
+    <!-- the module actually implements a very strict rule, it would be interesting to know whether Joshua meant what checkstyle implements. We feel this implementation 
+      is well suited as a warning, i.e. if you get error messages from this check you should be able to name a good reason to implement your code the way you do it, especially 
+      if you are designing a library and not an application. -->
+    <!-- <module name="DesignForExtension"> <property name="severity" value="warning"/> </module> -->
 
     <!-- Item 17 - Use interfaces only to define types -->
-    <module name="InterfaceIsType"/>
+    <module name="InterfaceIsType" />
 
     <!-- Item 25 - Design method signatures carefully -->
     <!-- Avoid long parameter lists -->
     <module name="ParameterNumber">
-      <property name="max" value="4"/>
+      <property name="max" value="4" />
     </module>
 
     <!-- Item 26 - Use overloading judiciously -->
@@ -86,38 +74,37 @@
 
     <!-- Item 28 - Write doc comments for all exposed API elements -->
     <module name="JavadocType">
-      <property name="scope" value="protected"/>
+      <property name="scope" value="protected" />
     </module>
     <module name="JavadocMethod"> <!-- also covers Item 44 -->
-      <property name="accessModifiers" value="protected"/>
+      <property name="accessModifiers" value="protected" />
     </module>
     <module name="JavadocVariable">
-      <property name="scope" value="protected"/>
+      <property name="scope" value="protected" />
     </module>
 
     <!-- Item 29 - Minimize the scope of local variables -->
     <!-- no rfe yet -->
 
-
     <!-- Item 38 - Adhere to generally accepted naming conventions -->
     <module name="PackageName">
       <!-- no uppercase letters, between 2 and 10 characters -->
-      <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]{1,9})*$"/>
+      <property name="format" value="^[a-z]+(\.[a-z][a-z0-9]{1,9})*$" />
     </module>
-    <module name="TypeName"/>
-    <module name="ConstantName"/>
-    <module name="LocalFinalVariableName"/>
-    <module name="LocalVariableName"/>
-    <module name="MemberName"/>
-    <module name="MethodName"/>
-    <module name="ParameterName"/>
-    <module name="StaticVariableName"/>
+    <module name="TypeName" />
+    <module name="ConstantName" />
+    <module name="LocalFinalVariableName" />
+    <module name="LocalVariableName" />
+    <module name="MemberName" />
+    <module name="MethodName" />
+    <module name="ParameterName" />
+    <module name="StaticVariableName" />
 
     <!-- Item 47 - Don't ignore exceptions -->
     <module name="EmptyBlock">
-      <property name="tokens" value="LITERAL_CATCH"/>
+      <property name="tokens" value="LITERAL_CATCH" />
       <!-- require a comment, change to stmt to require a statement -->
-      <property name="option" value="text"/>
+      <property name="option" value="text" />
     </module>
 
     <!-- Item 50 - Never invoke wait outside a loop -->
@@ -126,43 +113,58 @@
     <!-- Item 57 - Provide a readResolve method when necessary -->
     <!-- no rfe yet -->
 
-    <module name="MagicNumber"/>
+    <module name="MagicNumber" />
 
-    <module name="SuppressionCommentFilter"/>
+    <module name="SuppressionCommentFilter" />
 
-    <!-- 
-      Allow comment to suppress checkstyle for a single line
-      e.g. // CHECKSTYLE IGNORE MagicNumber
-     -->
+    <!-- Allow comment to suppress checkstyle for a single line e.g. // CHECKSTYLE IGNORE MagicNumber -->
     <module name="SuppressWithNearbyCommentFilter">
-      <property name="commentFormat" value="CHECKSTYLE IGNORE (\w+)"/>
-      <property name="checkFormat" value="$1"/>
+      <property name="commentFormat" value="CHECKSTYLE IGNORE (\w+)" />
+      <property name="checkFormat" value="$1" />
     </module>
-
-</module>
+    <module name="ImportOrder">
+      <property name="option" value="top"/>
+      <property name="groups" value="java,javax,org,junit"/>
+      <property name="ordered" value="true"/>
+      <property name="separated" value="true"/>
+    </module>
+    <module name="WhitespaceAround"/>
+    <module name="TypecastParenPad"/>
+    <module name="SingleSpaceSeparator"/>
+  </module>
 
   <!-- enforce package documentation -->
   <module name="JavadocPackage">
     <!-- setting allowLegacy means it will check for package.html instead of just package-info.java -->
-    <property name="allowLegacy" value="true"/>
+    <property name="allowLegacy" value="true" />
   </module>
-  
+
   <!-- Item 6 - Avoid finalizers -->
   <!-- this will not find violations that contain linebreaks -->
   <module name="RegexpSingleline">
-    <property name="format" value="((public)|(protected))\s+void\s+finalize\(\s*\)"/>
-     <property name="message" value="Avoid finalizers."/>
+    <property name="format" value="((public)|(protected))\s+void\s+finalize\(\s*\)" />
+    <property name="message" value="Avoid finalizers." />
   </module>
-    
+
   <!-- don't allow tabs -->
   <module name="FileTabCharacter">
-    <property name="fileExtensions" value="java,xml"/>
+    <property name="fileExtensions" value="java,xml" />
   </module>
 
   <module name="SuppressionFilter">
     <!-- config_loc is used by Eclipse plugin -->
-    <property name="file" value="${config_loc}/checkstyle-suppressions.xml"/>
+    <property name="file" value="${config_loc}/checkstyle-suppressions.xml" />
   </module>
-
-  
+  <module name="RegexpSingleline">
+    <!-- @author tags are deprecated -->
+    <property name="format" value="^\s+\*\s+@author\s" />
+    <property name="message" value="Deprecated @author tag" />
+    <property name="fileExtensions" value="java" />
+    <property name="severity" value="warning" />
+  </module>
+  <module name="RegexpSingleline">
+    <!-- \s matches whitespace character, $ matches end of line. -->
+    <property name="format" value="\s+$" />
+    <property name="message" value="Line has trailing spaces." />
+  </module>
 </module>
diff --git a/src/conf/spotbugs-exclude-filter.xml b/src/conf/spotbugs-exclude-filter.xml
new file mode 100644
index 0000000..ca6b09d
--- /dev/null
+++ b/src/conf/spotbugs-exclude-filter.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to You under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+-->
+<FindBugsFilter
+    xmlns="https://github.com/spotbugs/filter/3.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="https://github.com/spotbugs/filter/3.0.0 https://raw.githubusercontent.com/spotbugs/spotbugs/3.1.0/spotbugs/etc/findbugsfilter.xsd">
+  <!-- https://github.com/spotbugs/spotbugs/issues/2710 -->
+  <Match>
+    <Class name="~.*" />
+    <Bug pattern="CT_CONSTRUCTOR_THROW" />
+  </Match>
+  <Match>
+    <Class name="~.*" />
+    <Bug pattern="EI_EXPOSE_REP" />
+  </Match>  
+  <Match>
+    <Class name="~.*" />
+    <Bug pattern="EI_EXPOSE_REP2" />
+  </Match>
+  <!-- False positive?  
+  High: Class org.apache.commons.validator.routines.CreditCardValidator$1 defines non-transient non-serializable instance field val$creditCardRanges [org.apache.commons.validator.routines.CreditCardValidator$1] In CreditCardValidator.java SE_BAD_FIELD -->
+  <Match>
+    <Class name="org.apache.commons.validator.routines.CreditCardValidator$1" />
+    <Bug pattern="SE_BAD_FIELD" />
+  </Match>
+</FindBugsFilter>
diff --git a/src/main/java/org/apache/commons/validator/Arg.java b/src/main/java/org/apache/commons/validator/Arg.java
index f48a3da..09cc956 100644
--- a/src/main/java/org/apache/commons/validator/Arg.java
+++ b/src/main/java/org/apache/commons/validator/Arg.java
@@ -78,8 +78,8 @@
         try {
             return super.clone();
 
-        } catch(final CloneNotSupportedException e) {
-            throw new RuntimeException(e.toString());
+        } catch (final CloneNotSupportedException e) {
+            throw new UnsupportedOperationException(e.toString(), e);
         }
     }
 
@@ -118,7 +118,7 @@
 
     /**
      * Tests whether or not the key is a resource key or literal value.
-     * @return <code>true</code> if key is a resource key.
+     * @return {@code true} if key is a resource key.
      */
     public boolean isResource() {
         return this.resource;
@@ -150,7 +150,7 @@
     }
 
     /**
-     * Set this argument's replacement position.
+     * Sets this argument's replacement position.
      * @param position set this argument's replacement position.
      */
     public void setPosition(final int position) {
diff --git a/src/main/java/org/apache/commons/validator/CreditCardValidator.java b/src/main/java/org/apache/commons/validator/CreditCardValidator.java
index 56b6e43..971ae18 100644
--- a/src/main/java/org/apache/commons/validator/CreditCardValidator.java
+++ b/src/main/java/org/apache/commons/validator/CreditCardValidator.java
@@ -56,6 +56,71 @@
 @Deprecated
 public class CreditCardValidator {
 
+    private static class Amex implements CreditCardType {
+        static final Amex INSTANCE = new Amex();
+        private static final String PREFIX = "34,37,";
+        @Override
+        public boolean matches(final String card) {
+            final String prefix2 = card.substring(0, 2) + ",";
+            return PREFIX.contains(prefix2) && card.length() == 15;
+        }
+    }
+
+    /**
+     * CreditCardType implementations define how validation is performed
+     * for one type/brand of credit card.
+     * @since 1.1.2
+     */
+    public interface CreditCardType {
+
+        /**
+         * Returns true if the card number matches this type of credit
+         * card.  Note that this method is <strong>not</strong> responsible
+         * for analyzing the general form of the card number because
+         * <code>CreditCardValidator</code> performs those checks before
+         * calling this method.  It is generally only required to valid the
+         * length and prefix of the number to determine if it's the correct
+         * type.
+         * @param card The card number, never null.
+         * @return true if the number matches.
+         */
+        boolean matches(String card);
+
+    }
+
+    private static class Discover implements CreditCardType {
+        static final Discover INSTANCE = new Discover();
+        private static final String PREFIX = "6011";
+        @Override
+        public boolean matches(final String card) {
+            return card.substring(0, 4).equals(PREFIX) && card.length() == 16;
+        }
+    }
+
+    private static class Mastercard implements CreditCardType {
+        static final Mastercard INSTANCE = new Mastercard();
+        private static final String PREFIX = "51,52,53,54,55,";
+        @Override
+        public boolean matches(final String card) {
+            final String prefix2 = card.substring(0, 2) + ",";
+            return PREFIX.contains(prefix2) && card.length() == 16;
+        }
+    }
+
+    /**
+     *  Change to support Visa Carte Blue used in France
+     *  has been removed - see Bug 35926
+     */
+    private static class Visa implements CreditCardType {
+        static final Visa INSTANCE = new Visa();
+        private static final String PREFIX = "4";
+
+        @Override
+        public boolean matches(final String card) {
+            return card.substring(0, 1).equals(PREFIX) && (card.length() == 13 || card.length() == 16);
+        }
+    }
+
     /**
      * Option specifying that no cards are allowed.  This is useful if
      * you want only custom card types to validate so you turn off the
@@ -112,29 +177,39 @@
     public CreditCardValidator(final int options) {
         final Flags f = new Flags(options);
         if (f.isOn(VISA)) {
-            this.cardTypes.add(new Visa());
+            this.cardTypes.add(Visa.INSTANCE);
         }
 
         if (f.isOn(AMEX)) {
-            this.cardTypes.add(new Amex());
+            this.cardTypes.add(Amex.INSTANCE);
         }
 
         if (f.isOn(MASTERCARD)) {
-            this.cardTypes.add(new Mastercard());
+            this.cardTypes.add(Mastercard.INSTANCE);
         }
 
         if (f.isOn(DISCOVER)) {
-            this.cardTypes.add(new Discover());
+            this.cardTypes.add(Discover.INSTANCE);
         }
     }
 
     /**
+     * Adds an allowed CreditCardType that participates in the card
+     * validation algorithm.
+     * @param type The type that is now allowed to pass validation.
+     * @since 1.1.2
+     */
+    public void addAllowedCardType(final CreditCardType type){
+        this.cardTypes.add(type);
+    }
+
+    /**
      * Checks if the field is a valid credit card number.
      * @param card The card number to validate.
      * @return Whether the card number is valid.
      */
     public boolean isValid(final String card) {
-        if ((card == null) || (card.length() < 13) || (card.length() > 19)) {
+        if (card == null || card.length() < 13 || card.length() > 19) {
             return false;
         }
 
@@ -153,16 +228,6 @@
     }
 
     /**
-     * Adds an allowed CreditCardType that participates in the card
-     * validation algorithm.
-     * @param type The type that is now allowed to pass validation.
-     * @since 1.1.2
-     */
-    public void addAllowedCardType(final CreditCardType type){
-        this.cardTypes.add(type);
-    }
-
-    /**
      * Checks for a valid credit card number.
      * @param cardNumber Credit Card Number.
      * @return Whether the card number passes the luhnCheck.
@@ -176,11 +241,11 @@
             int digit = 0;
             try {
                 digit = Integer.parseInt(cardNumber.charAt(count) + "");
-            } catch(final NumberFormatException e) {
+            } catch (final NumberFormatException e) {
                 return false;
             }
 
-            if (((count & 1) ^ oddOrEven) == 0) { // not
+            if ((count & 1 ^ oddOrEven) == 0) { // not
                 digit *= 2;
                 if (digit > 9) {
                     digit -= 9;
@@ -189,69 +254,7 @@
             sum += digit;
         }
 
-        return (sum == 0) ? false : (sum % 10 == 0);
-    }
-
-    /**
-     * CreditCardType implementations define how validation is performed
-     * for one type/brand of credit card.
-     * @since 1.1.2
-     */
-    public interface CreditCardType {
-
-        /**
-         * Returns true if the card number matches this type of credit
-         * card.  Note that this method is <strong>not</strong> responsible
-         * for analyzing the general form of the card number because
-         * <code>CreditCardValidator</code> performs those checks before
-         * calling this method.  It is generally only required to valid the
-         * length and prefix of the number to determine if it's the correct
-         * type.
-         * @param card The card number, never null.
-         * @return true if the number matches.
-         */
-        boolean matches(String card);
-
-    }
-
-    /**
-     *  Change to support Visa Carte Blue used in France
-     *  has been removed - see Bug 35926
-     */
-    private static class Visa implements CreditCardType {
-        private static final String PREFIX = "4";
-        @Override
-        public boolean matches(final String card) {
-            return (
-                card.substring(0, 1).equals(PREFIX)
-                    && (card.length() == 13 || card.length() == 16));
-        }
-    }
-
-    private static class Amex implements CreditCardType {
-        private static final String PREFIX = "34,37,";
-        @Override
-        public boolean matches(final String card) {
-            final String prefix2 = card.substring(0, 2) + ",";
-            return ((PREFIX.contains(prefix2)) && (card.length() == 15));
-        }
-    }
-
-    private static class Discover implements CreditCardType {
-        private static final String PREFIX = "6011";
-        @Override
-        public boolean matches(final String card) {
-            return (card.substring(0, 4).equals(PREFIX) && (card.length() == 16));
-        }
-    }
-
-    private static class Mastercard implements CreditCardType {
-        private static final String PREFIX = "51,52,53,54,55,";
-        @Override
-        public boolean matches(final String card) {
-            final String prefix2 = card.substring(0, 2) + ",";
-            return ((PREFIX.contains(prefix2)) && (card.length() == 16));
-        }
+        return sum == 0 ? false : sum % 10 == 0;
     }
 
 }
diff --git a/src/main/java/org/apache/commons/validator/DateValidator.java b/src/main/java/org/apache/commons/validator/DateValidator.java
index 45546b2..febaf5b 100644
--- a/src/main/java/org/apache/commons/validator/DateValidator.java
+++ b/src/main/java/org/apache/commons/validator/DateValidator.java
@@ -55,46 +55,9 @@
     }
 
     /**
-     * <p>Checks if the field is a valid date.  The pattern is used with
-     * <code>java.text.SimpleDateFormat</code>.  If strict is true, then the
-     * length will be checked so '2/12/1999' will not pass validation with
-     * the format 'MM/dd/yyyy' because the month isn't two digits.
-     * The setLenient method is set to <code>false</code> for all.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param datePattern The pattern passed to <code>SimpleDateFormat</code>.
-     * @param strict Whether or not to have an exact match of the datePattern.
-     * @return true if the date is valid.
-     */
-    public boolean isValid(final String value, final String datePattern, final boolean strict) {
-
-        if (value == null
-                || datePattern == null
-                || datePattern.isEmpty()) {
-
-            return false;
-        }
-
-        final SimpleDateFormat formatter = new SimpleDateFormat(datePattern);
-        formatter.setLenient(false);
-
-        try {
-            formatter.parse(value);
-        } catch(final ParseException e) {
-            return false;
-        }
-
-        if (strict && (datePattern.length() != value.length())) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
      * <p>Checks if the field is a valid date.  The <code>Locale</code> is
      * used with <code>java.text.DateFormat</code>.  The setLenient method
-     * is set to <code>false</code> for all.</p>
+     * is set to {@code false} for all.</p>
      *
      * @param value The value validation is being performed on.
      * @param locale The locale to use for the date format, defaults to the default
@@ -121,7 +84,44 @@
 
         try {
             formatter.parse(value);
-        } catch(final ParseException e) {
+        } catch (final ParseException e) {
+            return false;
+        }
+
+        return true;
+    }
+
+    /**
+     * <p>Checks if the field is a valid date.  The pattern is used with
+     * <code>java.text.SimpleDateFormat</code>.  If strict is true, then the
+     * length will be checked so '2/12/1999' will not pass validation with
+     * the format 'MM/dd/yyyy' because the month isn't two digits.
+     * The setLenient method is set to {@code false} for all.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param datePattern The pattern passed to <code>SimpleDateFormat</code>.
+     * @param strict Whether or not to have an exact match of the datePattern.
+     * @return true if the date is valid.
+     */
+    public boolean isValid(final String value, final String datePattern, final boolean strict) {
+
+        if (value == null
+                || datePattern == null
+                || datePattern.isEmpty()) {
+
+            return false;
+        }
+
+        final SimpleDateFormat formatter = new SimpleDateFormat(datePattern);
+        formatter.setLenient(false);
+
+        try {
+            formatter.parse(value);
+        } catch (final ParseException e) {
+            return false;
+        }
+
+        if (strict && datePattern.length() != value.length()) {
             return false;
         }
 
diff --git a/src/main/java/org/apache/commons/validator/EmailValidator.java b/src/main/java/org/apache/commons/validator/EmailValidator.java
index 4952d8a..578fd83 100644
--- a/src/main/java/org/apache/commons/validator/EmailValidator.java
+++ b/src/main/java/org/apache/commons/validator/EmailValidator.java
@@ -28,7 +28,7 @@
  * </p>
  * <p>
  * Based on a script by <a href="mailto:stamhankar@hotmail.com">Sandeep V. Tamhankar</a>
- * http://javascript.internet.com
+ * https://javascript.internet.com
  * </p>
  * <p>
  * This implementation is not guaranteed to catch all possible errors in an email address.
@@ -80,7 +80,7 @@
     /**
      * <p>Checks if a field has a valid e-mail address.</p>
      *
-     * @param email The value validation is being performed on.  A <code>null</code>
+     * @param email The value validation is being performed on.  A {@code null}
      * value is considered invalid.
      * @return true if the email address is valid.
      */
@@ -121,15 +121,6 @@
     }
 
     /**
-     * Returns true if the user component of an email address is valid.
-     * @param user being validated
-     * @return true if the user name is valid.
-     */
-    protected boolean isValidUser(final String user) {
-        return USER_PATTERN.matcher(user).matches();
-    }
-
-    /**
      * Validates an IP address. Returns true if valid.
      * @param ipAddress IP address
      * @return true if the ip address is valid.
@@ -146,7 +137,7 @@
 
             try {
                 iIpSegment = Integer.parseInt(ipSegment);
-            } catch(final NumberFormatException e) {
+            } catch (final NumberFormatException e) {
                 return false;
             }
 
@@ -174,7 +165,7 @@
                 domainSegment[i] = atomMatcher.group(1);
                 final int l = domainSegment[i].length() + 1;
                 domain =
-                        (l >= domain.length())
+                        l >= domain.length()
                         ? ""
                         : domain.substring(l);
 
@@ -199,22 +190,31 @@
 
         return true;
     }
+
     /**
-     *   Recursively remove comments, and replace with a single space.  The simpler
-     *   regexps in the Email Addressing FAQ are imperfect - they will miss escaped
-     *   chars in atoms, for example.
-     *   Derived From    Mail::RFC822::Address
+     * Returns true if the user component of an email address is valid.
+     * @param user being validated
+     * @return true if the user name is valid.
+     */
+    protected boolean isValidUser(final String user) {
+        return USER_PATTERN.matcher(user).matches();
+    }
+
+    /**
+     * Recursively remove comments, and replace with a single space. The simpler regexps in the Email Addressing FAQ are imperfect - they will miss escaped
+     * chars in atoms, for example. Derived From Mail::RFC822::Address
+     *
      * @param emailStr The email address
      * @return address with comments removed.
-    */
-    protected String stripComments(final String emailStr)  {
-     String result = emailStr;
-     final String commentPat = "^((?:[^\"\\\\]|\\\\.)*(?:\"(?:[^\"\\\\]|\\\\.)*\"(?:[^\"\\\\]|\111111\\\\.)*)*)\\((?:[^()\\\\]|\\\\.)*\\)/";
-     final Pattern commentMatcher = Pattern.compile(commentPat);
+     */
+    protected String stripComments(final String emailStr) {
+        String result = emailStr;
+        final String commentPat = "^((?:[^\"\\\\]|\\\\.)*(?:\"(?:[^\"\\\\]|\\\\.)*\"(?:[^\"\\\\]|\111111\\\\.)*)*)\\((?:[^()\\\\]|\\\\.)*\\)/";
+        final Pattern commentMatcher = Pattern.compile(commentPat);
 
-     while (commentMatcher.matcher(result).matches()) {
-        result = result.replaceFirst(commentPat, "\1 ");
-     }
-     return result;
+        while (commentMatcher.matcher(result).matches()) {
+            result = result.replaceFirst(commentPat, "\1 ");
+        }
+        return result;
     }
 }
diff --git a/src/main/java/org/apache/commons/validator/Field.java b/src/main/java/org/apache/commons/validator/Field.java
index 513ec13..cf10b80 100644
--- a/src/main/java/org/apache/commons/validator/Field.java
+++ b/src/main/java/org/apache/commons/validator/Field.java
@@ -123,7 +123,7 @@
      * synchronized so a call to setDepends() (which clears the List) won't
      * interfere with a call to isDependency().
      */
-    private final List<String> dependencyList = Collections.synchronizedList(new ArrayList<String>());
+    private final List<String> dependencyList = Collections.synchronizedList(new ArrayList<>());
 
     /**
      * @deprecated Subclasses should use getVarMap() instead.
@@ -147,181 +147,6 @@
     protected Map<String, Arg>[] args = new Map[0];
 
     /**
-     * Gets the page value that the Field is associated with for
-     * validation.
-     * @return The page number.
-     */
-    public int getPage() {
-        return this.page;
-    }
-
-    /**
-     * Sets the page value that the Field is associated with for
-     * validation.
-     * @param page The page number.
-     */
-    public void setPage(final int page) {
-        this.page = page;
-    }
-
-    /**
-     * Gets the position of the <code>Field</code> in the validation list.
-     * @return The field position.
-     */
-    public int getFieldOrder() {
-        return this.fieldOrder;
-    }
-
-    /**
-     * Sets the position of the <code>Field</code> in the validation list.
-     * @param fieldOrder The field position.
-     */
-    public void setFieldOrder(final int fieldOrder) {
-        this.fieldOrder = fieldOrder;
-    }
-
-    /**
-     * Gets the property name of the field.
-     * @return The field's property name.
-     */
-    public String getProperty() {
-        return this.property;
-    }
-
-    /**
-     * Sets the property name of the field.
-     * @param property The field's property name.
-     */
-    public void setProperty(final String property) {
-        this.property = property;
-    }
-
-    /**
-     * Gets the indexed property name of the field.  This
-     * is the method name that can take an <code>int</code> as
-     * a parameter for indexed property value retrieval.
-     * @return The field's indexed property name.
-     */
-    public String getIndexedProperty() {
-        return this.indexedProperty;
-    }
-
-    /**
-     * Sets the indexed property name of the field.
-     * @param indexedProperty The field's indexed property name.
-     */
-    public void setIndexedProperty(final String indexedProperty) {
-        this.indexedProperty = indexedProperty;
-    }
-
-    /**
-     * Gets the indexed property name of the field.  This
-     * is the method name that will return an array or a
-     * <code>Collection</code> used to retrieve the
-     * list and then loop through the list performing the specified
-     * validations.
-     * @return The field's indexed List property name.
-     */
-    public String getIndexedListProperty() {
-        return this.indexedListProperty;
-    }
-
-    /**
-     * Sets the indexed property name of the field.
-     * @param indexedListProperty The field's indexed List property name.
-     */
-    public void setIndexedListProperty(final String indexedListProperty) {
-        this.indexedListProperty = indexedListProperty;
-    }
-
-    /**
-     * Gets the validation rules for this field as a comma separated list.
-     * @return A comma separated list of validator names.
-     */
-    public String getDepends() {
-        return this.depends;
-    }
-
-    /**
-     * Sets the validation rules for this field as a comma separated list.
-     * @param depends A comma separated list of validator names.
-     */
-    public void setDepends(final String depends) {
-        this.depends = depends;
-
-        this.dependencyList.clear();
-
-        final StringTokenizer st = new StringTokenizer(depends, ",");
-        while (st.hasMoreTokens()) {
-            final String depend = st.nextToken().trim();
-
-            if (depend != null && !depend.isEmpty()) {
-                this.dependencyList.add(depend);
-            }
-        }
-    }
-
-    /**
-     * Add a <code>Msg</code> to the <code>Field</code>.
-     * @param msg A validation message.
-     */
-    public void addMsg(final Msg msg) {
-        getMsgMap().put(msg.getName(), msg);
-    }
-
-    /**
-     * Retrieve a message value.
-     * @param key Validation key.
-     * @return A validation message for a specified validator.
-     */
-    public String getMsg(final String key) {
-        final Msg msg = getMessage(key);
-        return (msg == null) ? null : msg.getKey();
-    }
-
-    /**
-     * Retrieve a message object.
-     * @since 1.1.4
-     * @param key Validation key.
-     * @return A validation message for a specified validator.
-     */
-    public Msg getMessage(final String key) {
-        return getMsgMap().get(key);
-    }
-
-    /**
-     * The <code>Field</code>'s messages are returned as an
-     * unmodifiable <code>Map</code>.
-     * @since 1.1.4
-     * @return Map of validation messages for the field.
-     */
-    public Map<String, Msg> getMessages() {
-        return Collections.unmodifiableMap(getMsgMap());
-    }
-
-    /**
-     * Determines whether client-side scripting should be generated
-     * for this field. The default is <code>true</code>
-     * @return <code>true</code> for scripting; otherwise false
-     * @see #setClientValidation(boolean)
-     * @since 1.4
-     */
-    public boolean isClientValidation() {
-        return this.clientValidation;
-    }
-
-    /**
-     * Sets the flag that determines whether client-side scripting should
-     * be generated for this field.
-     * @param clientValidation the scripting flag
-     * @see #isClientValidation()
-     * @since 1.4
-     */
-    public void setClientValidation(final boolean clientValidation) {
-        this.clientValidation = clientValidation;
-    }
-
-    /**
      * Add an <code>Arg</code> to the replacement argument list.
      * @since 1.1
      * @param arg Validation message's argument.
@@ -350,6 +175,65 @@
     }
 
     /**
+     * Add a <code>Msg</code> to the <code>Field</code>.
+     * @param msg A validation message.
+     */
+    public void addMsg(final Msg msg) {
+        getMsgMap().put(msg.getName(), msg);
+    }
+
+    /**
+     * Add a <code>Var</code>, based on the values passed in, to the
+     * <code>Field</code>.
+     * @param name Name of the validation.
+     * @param value The Argument's value.
+     * @param jsType The JavaScript type.
+     */
+    public void addVar(final String name, final String value, final String jsType) {
+        this.addVar(new Var(name, value, jsType));
+    }
+
+    /**
+     * Add a <code>Var</code> to the <code>Field</code>.
+     * @param v The Validator Argument.
+     */
+    public void addVar(final Var v) {
+        this.getVarMap().put(v.getName(), v);
+    }
+
+    /**
+     * Creates and returns a copy of this object.
+     * @return A copy of the Field.
+     */
+    @Override
+    public Object clone() {
+        Field field = null;
+        try {
+            field = (Field) super.clone();
+        } catch (final CloneNotSupportedException e) {
+            throw new UnsupportedOperationException(e.toString(), e);
+        }
+
+        @SuppressWarnings("unchecked") // empty array always OK; cannot check this at compile time
+        final Map<String, Arg>[] tempMap = new Map[this.args.length];
+        field.args = tempMap;
+        for (int i = 0; i < this.args.length; i++) {
+            if (this.args[i] == null) {
+                continue;
+            }
+
+            final Map<String, Arg> argMap = new HashMap<>(this.args[i]);
+            argMap.forEach((validatorName, arg) -> argMap.put(validatorName, (Arg) arg.clone()));
+            field.args[i] = argMap;
+        }
+
+        field.hVars = ValidatorUtils.copyFastHashMap(hVars);
+        field.hMsgs = ValidatorUtils.copyFastHashMap(hMsgs);
+
+        return field;
+    }
+
+    /**
      * Calculate the position of the Arg
      */
     private void determineArgPosition(final Arg arg) {
@@ -371,7 +255,7 @@
         // the same name or the last default argument
         final String keyName = arg.getName() == null ? DEFAULT_ARG : arg.getName();
         int lastPosition = -1;
-        int lastDefault  = -1;
+        int lastDefault = -1;
         for (int i = 0; i < args.length; i++) {
             if (args[i] != null && args[i].containsKey(keyName)) {
                 lastPosition = i;
@@ -407,6 +291,17 @@
     }
 
     /**
+     * Generate correct <code>key</code> value.
+     */
+    public void generateKey() {
+        if (this.isIndexed()) {
+            this.key = this.indexedListProperty + TOKEN_INDEXED + "." + this.property;
+        } else {
+            this.key = this.property;
+        }
+    }
+
+    /**
      * Gets the default <code>Arg</code> object at the given position.
      * @param position Validation message argument's position.
      * @return The default Arg or null if not found.
@@ -418,7 +313,7 @@
 
     /**
      * Gets the <code>Arg</code> object at the given position.  If the key
-     * finds a <code>null</code> value then the default value will be
+     * finds a {@code null} value then the default value will be
      * retrieved.
      * @param key The name the Arg is stored under.  If not found, the default
      * Arg for the given position (if any) will be retrieved.
@@ -427,7 +322,7 @@
      * @since 1.1
      */
     public Arg getArg(final String key, final int position) {
-        if ((position >= this.args.length) || (this.args[position] == null)) {
+        if (position >= this.args.length || this.args[position] == null) {
             return null;
         }
 
@@ -435,11 +330,11 @@
 
         // Didn't find default arg so exit, otherwise we would get into
         // infinite recursion
-        if ((arg == null) && key.equals(DEFAULT_ARG)) {
+        if (arg == null && key.equals(DEFAULT_ARG)) {
             return null;
         }
 
-        return (arg == null) ? this.getArg(position) : arg;
+        return arg == null ? this.getArg(position) : arg;
     }
 
     /**
@@ -449,7 +344,7 @@
      * has a position of 0).
      * @since 1.1.1
      */
-    public Arg[] getArgs(final String key){
+    public Arg[] getArgs(final String key) {
         final Arg[] argList = new Arg[this.args.length];
 
         for (int i = 0; i < this.args.length; i++) {
@@ -460,22 +355,178 @@
     }
 
     /**
-     * Add a <code>Var</code> to the <code>Field</code>.
-     * @param v The Validator Argument.
+     * Gets an unmodifiable <code>List</code> of the dependencies in the same
+     * order they were defined in parameter passed to the setDepends() method.
+     * @return A list of the Field's dependancies.
      */
-    public void addVar(final Var v) {
-        this.getVarMap().put(v.getName(), v);
+    public List<String> getDependencyList() {
+        return Collections.unmodifiableList(this.dependencyList);
     }
 
     /**
-     * Add a <code>Var</code>, based on the values passed in, to the
-     * <code>Field</code>.
-     * @param name Name of the validation.
-     * @param value The Argument's value.
-     * @param jsType The Javascript type.
+     * Gets the validation rules for this field as a comma separated list.
+     * @return A comma separated list of validator names.
      */
-    public void addVar(final String name, final String value, final String jsType) {
-        this.addVar(new Var(name, value, jsType));
+    public String getDepends() {
+        return this.depends;
+    }
+
+    /**
+     * Gets the position of the <code>Field</code> in the validation list.
+     * @return The field position.
+     */
+    public int getFieldOrder() {
+        return this.fieldOrder;
+    }
+
+    /**
+     * Gets the indexed property name of the field.  This
+     * is the method name that will return an array or a
+     * <code>Collection</code> used to retrieve the
+     * list and then loop through the list performing the specified
+     * validations.
+     * @return The field's indexed List property name.
+     */
+    public String getIndexedListProperty() {
+        return this.indexedListProperty;
+    }
+
+    /**
+     * Gets the indexed property name of the field.  This
+     * is the method name that can take an <code>int</code> as
+     * a parameter for indexed property value retrieval.
+     * @return The field's indexed property name.
+     */
+    public String getIndexedProperty() {
+        return this.indexedProperty;
+    }
+
+    /**
+     * Returns an indexed property from the object we're validating.
+     *
+     * @param bean The bean to extract the indexed values from.
+     * @throws ValidatorException If there's an error looking up the property
+     * or, the property found is not indexed.
+     */
+    Object[] getIndexedProperty(final Object bean) throws ValidatorException {
+        Object indexProp = null;
+
+        try {
+            indexProp = PropertyUtils.getProperty(bean, this.getIndexedListProperty());
+
+        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+            throw new ValidatorException(e.getMessage());
+        }
+
+        if (indexProp instanceof Collection) {
+            return ((Collection<?>) indexProp).toArray();
+
+        }
+        if (indexProp.getClass().isArray()) {
+            return (Object[]) indexProp;
+
+        }
+        throw new ValidatorException(this.getKey() + " is not indexed");
+
+    }
+
+    /**
+     * Returns the size of an indexed property from the object we're validating.
+     *
+     * @param bean The bean to extract the indexed values from.
+     * @throws ValidatorException If there's an error looking up the property
+     * or, the property found is not indexed.
+     */
+    private int getIndexedPropertySize(final Object bean) throws ValidatorException {
+        Object indexProp = null;
+
+        try {
+            indexProp = PropertyUtils.getProperty(bean, this.getIndexedListProperty());
+
+        } catch (IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+            throw new ValidatorException(e.getMessage());
+        }
+
+        if (indexProp == null) {
+            return 0;
+        }
+        if (indexProp instanceof Collection) {
+            return ((Collection<?>) indexProp).size();
+        }
+        if (indexProp.getClass().isArray()) {
+            return ((Object[]) indexProp).length;
+        }
+        throw new ValidatorException(this.getKey() + " is not indexed");
+
+    }
+
+    /**
+     * Gets a unique key based on the property and indexedProperty fields.
+     * @return a unique key for the field.
+     */
+    public String getKey() {
+        if (this.key == null) {
+            this.generateKey();
+        }
+
+        return this.key;
+    }
+
+    /**
+     * Retrieve a message object.
+     * @since 1.1.4
+     * @param key Validation key.
+     * @return A validation message for a specified validator.
+     */
+    public Msg getMessage(final String key) {
+        return getMsgMap().get(key);
+    }
+
+    /**
+     * The <code>Field</code>'s messages are returned as an
+     * unmodifiable <code>Map</code>.
+     * @since 1.1.4
+     * @return Map of validation messages for the field.
+     */
+    public Map<String, Msg> getMessages() {
+        return Collections.unmodifiableMap(getMsgMap());
+    }
+
+    /**
+     * Retrieve a message value.
+     * @param key Validation key.
+     * @return A validation message for a specified validator.
+     */
+    public String getMsg(final String key) {
+        final Msg msg = getMessage(key);
+        return msg == null ? null : msg.getKey();
+    }
+
+    /**
+     * Returns a Map of String Msg names to Msg objects.
+     * @since 1.2.0
+     * @return A Map of the Field's messages.
+     */
+    @SuppressWarnings("unchecked") // FastHashMap does not support generics
+    protected Map<String, Msg> getMsgMap() {
+        return hMsgs;
+    }
+
+    /**
+     * Gets the page value that the Field is associated with for
+     * validation.
+     * @return The page number.
+     */
+    public int getPage() {
+        return this.page;
+    }
+
+    /**
+     * Gets the property name of the field.
+     * @return The field's property name.
+     */
+    public String getProperty() {
+        return this.property;
     }
 
     /**
@@ -488,6 +539,25 @@
     }
 
     /**
+     * Returns a Map of String Var names to Var objects.
+     * @since 1.2.0
+     * @return A Map of the Field's variables.
+     */
+    @SuppressWarnings("unchecked") // FastHashMap does not support generics
+    protected Map<String, Var> getVarMap() {
+        return hVars;
+    }
+
+    /**
+     * The <code>Field</code>'s variables are returned as an
+     * unmodifiable <code>Map</code>.
+     * @return the Map of Variable's for a Field.
+     */
+    public Map<String, Var> getVars() {
+        return Collections.unmodifiableMap(getVarMap());
+    }
+
+    /**
      * Retrieve a variable's value.
      * @param mainKey The Variable's key
      * @return the Variable's value
@@ -504,54 +574,44 @@
     }
 
     /**
-     * The <code>Field</code>'s variables are returned as an
-     * unmodifiable <code>Map</code>.
-     * @return the Map of Variable's for a Field.
+     * Called when a validator name is used in a depends clause but there is
+     * no know ValidatorAction configured for that name.
+     * @param name The name of the validator in the depends list.
+     * @throws ValidatorException
      */
-    public Map<String, Var> getVars() {
-        return Collections.unmodifiableMap(getVarMap());
+    private void handleMissingAction(final String name) throws ValidatorException {
+        throw new ValidatorException("No ValidatorAction named " + name
+                + " found for field " + this.getProperty());
     }
 
     /**
-     * Gets a unique key based on the property and indexedProperty fields.
-     * @return a unique key for the field.
+     * Determines whether client-side scripting should be generated
+     * for this field. The default is {@code true}
+     * @return {@code true} for scripting; otherwise false
+     * @see #setClientValidation(boolean)
+     * @since 1.4
      */
-    public String getKey() {
-        if (this.key == null) {
-            this.generateKey();
-        }
-
-        return this.key;
+    public boolean isClientValidation() {
+        return this.clientValidation;
     }
 
     /**
-     * Sets a unique key for the field.  This can be used to change
-     * the key temporarily to have a unique key for an indexed field.
-     * @param key a unique key for the field
+     * Checks if the validator is listed as a dependency.
+     * @param validatorName Name of the validator to check.
+     * @return Whether the field is dependant on a validator.
      */
-    public void setKey(final String key) {
-        this.key = key;
+    public boolean isDependency(final String validatorName) {
+        return this.dependencyList.contains(validatorName);
     }
 
     /**
      * If there is a value specified for the indexedProperty field then
-     * <code>true</code> will be returned.  Otherwise it will be
-     * <code>false</code>.
+     * {@code true} will be returned.  Otherwise it will be
+     * {@code false}.
      * @return Whether the Field is indexed.
      */
     public boolean isIndexed() {
-        return (indexedListProperty != null && !indexedListProperty.isEmpty());
-    }
-
-    /**
-     * Generate correct <code>key</code> value.
-     */
-    public void generateKey() {
-        if (this.isIndexed()) {
-            this.key = this.indexedListProperty + TOKEN_INDEXED + "." + this.property;
-        } else {
-            this.key = this.property;
-        }
+        return indexedListProperty != null && !indexedListProperty.isEmpty();
     }
 
     /**
@@ -603,14 +663,20 @@
     }
 
     /**
-     * Replace the vars value with the key/value pairs passed in.
+     * Replace the arg <code>Collection</code> key value with the key/value
+     * pairs passed in.
      */
-    private void processVars(final String key, final String replaceValue) {
-        for (final String varKey : getVarMap().keySet()) {
-            final Var var = this.getVar(varKey);
-            var.setValue(ValidatorUtils.replace(var.getValue(), key, replaceValue));
+    private void processArg(final String key, final String replaceValue) {
+        for (final Map<String, Arg> argMap : this.args) {
+            if (argMap == null) {
+                continue;
+            }
+            for (final Arg arg : argMap.values()) {
+                if (arg != null) {
+                    arg.setKey(ValidatorUtils.replace(arg.getKey(), key, replaceValue));
+                }
+            }
         }
-
     }
 
     /**
@@ -629,185 +695,14 @@
     }
 
     /**
-     * Replace the arg <code>Collection</code> key value with the key/value
-     * pairs passed in.
+     * Replace the vars value with the key/value pairs passed in.
      */
-    private void processArg(final String key, final String replaceValue) {
-        for (final Map<String, Arg> argMap : this.args) {
-            if (argMap == null) {
-                continue;
-            }
-            for (final Arg arg : argMap.values()) {
-                if (arg != null) {
-                    arg.setKey(ValidatorUtils.replace(arg.getKey(), key, replaceValue));
-                }
-            }
-        }
-    }
-
-    /**
-     * Checks if the validator is listed as a dependency.
-     * @param validatorName Name of the validator to check.
-     * @return Whether the field is dependant on a validator.
-     */
-    public boolean isDependency(final String validatorName) {
-        return this.dependencyList.contains(validatorName);
-    }
-
-    /**
-     * Gets an unmodifiable <code>List</code> of the dependencies in the same
-     * order they were defined in parameter passed to the setDepends() method.
-     * @return A list of the Field's dependancies.
-     */
-    public List<String> getDependencyList() {
-        return Collections.unmodifiableList(this.dependencyList);
-    }
-
-    /**
-     * Creates and returns a copy of this object.
-     * @return A copy of the Field.
-     */
-    @Override
-    public Object clone() {
-        Field field = null;
-        try {
-            field = (Field) super.clone();
-        } catch(final CloneNotSupportedException e) {
-            throw new RuntimeException(e.toString());
+    private void processVars(final String key, final String replaceValue) {
+        for (final String varKey : getVarMap().keySet()) {
+            final Var var = this.getVar(varKey);
+            var.setValue(ValidatorUtils.replace(var.getValue(), key, replaceValue));
         }
 
-        @SuppressWarnings("unchecked") // empty array always OK; cannot check this at compile time
-        final Map<String, Arg>[] tempMap = new Map[this.args.length];
-        field.args = tempMap;
-        for (int i = 0; i < this.args.length; i++) {
-            if (this.args[i] == null) {
-                continue;
-            }
-
-            final Map<String, Arg> argMap = new HashMap<>(this.args[i]);
-            argMap.forEach((validatorName, arg) -> argMap.put(validatorName, (Arg) arg.clone()));
-            field.args[i] = argMap;
-        }
-
-        field.hVars = ValidatorUtils.copyFastHashMap(hVars);
-        field.hMsgs = ValidatorUtils.copyFastHashMap(hMsgs);
-
-        return field;
-    }
-
-    /**
-     * Returns a string representation of the object.
-     * @return A string representation of the object.
-     */
-    @Override
-    public String toString() {
-        final StringBuilder results = new StringBuilder();
-
-        results.append("\t\tkey = " + key + "\n");
-        results.append("\t\tproperty = " + property + "\n");
-        results.append("\t\tindexedProperty = " + indexedProperty + "\n");
-        results.append("\t\tindexedListProperty = " + indexedListProperty + "\n");
-        results.append("\t\tdepends = " + depends + "\n");
-        results.append("\t\tpage = " + page + "\n");
-        results.append("\t\tfieldOrder = " + fieldOrder + "\n");
-
-        if (hVars != null) {
-            results.append("\t\tVars:\n");
-            for (final Object key1 : getVarMap().keySet()) {
-                results.append("\t\t\t");
-                results.append(key1);
-                results.append("=");
-                results.append(getVarMap().get(key1));
-                results.append("\n");
-            }
-        }
-
-        return results.toString();
-    }
-
-    /**
-     * Returns an indexed property from the object we're validating.
-     *
-     * @param bean The bean to extract the indexed values from.
-     * @throws ValidatorException If there's an error looking up the property
-     * or, the property found is not indexed.
-     */
-    Object[] getIndexedProperty(final Object bean) throws ValidatorException {
-        Object indexProp = null;
-
-        try {
-            indexProp =
-                PropertyUtils.getProperty(bean, this.getIndexedListProperty());
-
-        } catch(IllegalAccessException|InvocationTargetException|NoSuchMethodException e) {
-            throw new ValidatorException(e.getMessage());
-        }
-
-        if (indexProp instanceof Collection) {
-            return ((Collection<?>) indexProp).toArray();
-
-        }
-        if (indexProp.getClass().isArray()) {
-            return (Object[]) indexProp;
-
-        }
-        throw new ValidatorException(this.getKey() + " is not indexed");
-
-    }
-    /**
-     * Returns the size of an indexed property from the object we're validating.
-     *
-     * @param bean The bean to extract the indexed values from.
-     * @throws ValidatorException If there's an error looking up the property
-     * or, the property found is not indexed.
-     */
-    private int getIndexedPropertySize(final Object bean) throws ValidatorException {
-        Object indexProp = null;
-
-        try {
-            indexProp =
-                PropertyUtils.getProperty(bean, this.getIndexedListProperty());
-
-        } catch(IllegalAccessException|InvocationTargetException|NoSuchMethodException e) {
-            throw new ValidatorException(e.getMessage());
-        }
-
-        if (indexProp == null) {
-            return 0;
-        }
-        if (indexProp instanceof Collection) {
-            return ((Collection<?>)indexProp).size();
-        }
-        if (indexProp.getClass().isArray()) {
-            return ((Object[])indexProp).length;
-        }
-        throw new ValidatorException(this.getKey() + " is not indexed");
-
-    }
-
-    /**
-     * Executes the given ValidatorAction and all ValidatorActions that it
-     * depends on.
-     * @return true if the validation succeeded.
-     */
-    private boolean validateForRule(
-        final ValidatorAction va,
-        final ValidatorResults results,
-        final Map<String, ValidatorAction> actions,
-        final Map<String, Object> params,
-        final int pos)
-        throws ValidatorException {
-
-        final ValidatorResult result = results.getValidatorResult(this.getKey());
-        if (result != null && result.containsAction(va.getName())) {
-            return result.isValid(va.getName());
-        }
-
-        if (!this.runDependentValidators(va, results, actions, params, pos)) {
-            return false;
-        }
-
-        return va.executeValidationMethod(this, params, results, pos);
     }
 
     /**
@@ -849,6 +744,115 @@
     }
 
     /**
+     * Sets the flag that determines whether client-side scripting should
+     * be generated for this field.
+     * @param clientValidation the scripting flag
+     * @see #isClientValidation()
+     * @since 1.4
+     */
+    public void setClientValidation(final boolean clientValidation) {
+        this.clientValidation = clientValidation;
+    }
+
+    /**
+     * Sets the validation rules for this field as a comma separated list.
+     * @param depends A comma separated list of validator names.
+     */
+    public void setDepends(final String depends) {
+        this.depends = depends;
+
+        this.dependencyList.clear();
+
+        final StringTokenizer st = new StringTokenizer(depends, ",");
+        while (st.hasMoreTokens()) {
+            final String depend = st.nextToken().trim();
+
+            if (depend != null && !depend.isEmpty()) {
+                this.dependencyList.add(depend);
+            }
+        }
+    }
+
+    /**
+     * Sets the position of the <code>Field</code> in the validation list.
+     * @param fieldOrder The field position.
+     */
+    public void setFieldOrder(final int fieldOrder) {
+        this.fieldOrder = fieldOrder;
+    }
+
+    /**
+     * Sets the indexed property name of the field.
+     * @param indexedListProperty The field's indexed List property name.
+     */
+    public void setIndexedListProperty(final String indexedListProperty) {
+        this.indexedListProperty = indexedListProperty;
+    }
+    /**
+     * Sets the indexed property name of the field.
+     * @param indexedProperty The field's indexed property name.
+     */
+    public void setIndexedProperty(final String indexedProperty) {
+        this.indexedProperty = indexedProperty;
+    }
+
+    /**
+     * Sets a unique key for the field.  This can be used to change
+     * the key temporarily to have a unique key for an indexed field.
+     * @param key a unique key for the field
+     */
+    public void setKey(final String key) {
+        this.key = key;
+    }
+
+    /**
+     * Sets the page value that the Field is associated with for
+     * validation.
+     * @param page The page number.
+     */
+    public void setPage(final int page) {
+        this.page = page;
+    }
+
+    /**
+     * Sets the property name of the field.
+     * @param property The field's property name.
+     */
+    public void setProperty(final String property) {
+        this.property = property;
+    }
+
+    /**
+     * Returns a string representation of the object.
+     * @return A string representation of the object.
+     */
+    @Override
+    public String toString() {
+        final StringBuilder results = new StringBuilder();
+
+        results.append("\t\tkey = " + key + "\n");
+        results.append("\t\tproperty = " + property + "\n");
+        results.append("\t\tindexedProperty = " + indexedProperty + "\n");
+        results.append("\t\tindexedListProperty = " + indexedListProperty + "\n");
+        results.append("\t\tdepends = " + depends + "\n");
+        results.append("\t\tpage = " + page + "\n");
+        results.append("\t\tfieldOrder = " + fieldOrder + "\n");
+
+        if (hVars != null) {
+            results.append("\t\tVars:\n");
+            for (final Object key1 : getVarMap().keySet()) {
+                results.append("\t\t\t");
+                results.append(key1);
+                results.append("=");
+                results.append(getVarMap().get(key1));
+                results.append("\n");
+            }
+        }
+
+        return results.toString();
+    }
+
+    /**
      * Run the configured validations on this field.  Run all validations
      * in the depends clause over each item in turn, returning when the first
      * one fails.
@@ -860,7 +864,7 @@
      * @throws ValidatorException If an error occurs during validation.
      */
     public ValidatorResults validate(final Map<String, Object> params, final Map<String, ValidatorAction> actions)
-        throws ValidatorException {
+            throws ValidatorException {
 
         if (this.getDepends() == null) {
             return new ValidatorResults();
@@ -869,13 +873,12 @@
         final ValidatorResults allResults = new ValidatorResults();
 
         final Object bean = params.get(Validator.BEAN_PARAM);
-        final int numberOfFieldsToValidate =
-            this.isIndexed() ? this.getIndexedPropertySize(bean) : 1;
+        final int numberOfFieldsToValidate = this.isIndexed() ? this.getIndexedPropertySize(bean) : 1;
 
         for (int fieldNumber = 0; fieldNumber < numberOfFieldsToValidate; fieldNumber++) {
 
             final ValidatorResults results = new ValidatorResults();
-            synchronized(dependencyList) {
+            synchronized (dependencyList) {
                 for (final String depend : this.dependencyList) {
 
                     final ValidatorAction action = actions.get(depend);
@@ -883,8 +886,7 @@
                         this.handleMissingAction(depend);
                     }
 
-                    final boolean good =
-                        validateForRule(action, results, actions, params, fieldNumber);
+                    final boolean good = validateForRule(action, results, actions, params, fieldNumber);
 
                     if (!good) {
                         allResults.merge(results);
@@ -899,34 +901,28 @@
     }
 
     /**
-     * Called when a validator name is used in a depends clause but there is
-     * no know ValidatorAction configured for that name.
-     * @param name The name of the validator in the depends list.
-     * @throws ValidatorException
+     * Executes the given ValidatorAction and all ValidatorActions that it
+     * depends on.
+     * @return true if the validation succeeded.
      */
-    private void handleMissingAction(final String name) throws ValidatorException {
-        throw new ValidatorException("No ValidatorAction named " + name
-                + " found for field " + this.getProperty());
-    }
+    private boolean validateForRule(
+        final ValidatorAction va,
+        final ValidatorResults results,
+        final Map<String, ValidatorAction> actions,
+        final Map<String, Object> params,
+        final int pos)
+        throws ValidatorException {
 
-    /**
-     * Returns a Map of String Msg names to Msg objects.
-     * @since 1.2.0
-     * @return A Map of the Field's messages.
-     */
-    @SuppressWarnings("unchecked") // FastHashMap does not support generics
-    protected Map<String, Msg> getMsgMap() {
-        return hMsgs;
-    }
+        final ValidatorResult result = results.getValidatorResult(this.getKey());
+        if (result != null && result.containsAction(va.getName())) {
+            return result.isValid(va.getName());
+        }
 
-    /**
-     * Returns a Map of String Var names to Var objects.
-     * @since 1.2.0
-     * @return A Map of the Field's variables.
-     */
-    @SuppressWarnings("unchecked") // FastHashMap does not support generics
-    protected Map<String, Var> getVarMap() {
-        return hVars;
+        if (!this.runDependentValidators(va, results, actions, params, pos)) {
+            return false;
+        }
+
+        return va.executeValidationMethod(this, params, results, pos);
     }
 }
 
diff --git a/src/main/java/org/apache/commons/validator/Form.java b/src/main/java/org/apache/commons/validator/Form.java
index ec87ac2..fa4c12f 100644
--- a/src/main/java/org/apache/commons/validator/Form.java
+++ b/src/main/java/org/apache/commons/validator/Form.java
@@ -27,13 +27,14 @@
 
 /**
  * <p>
- *
  * This contains a set of validation rules for a form/JavaBean. The information
  * is contained in a list of <code>Field</code> objects. Instances of this class
- * are configured with a &lt;form&gt; xml element. </p> <p>
- *
+ * are configured with a &lt;form&gt; xml element.
+ * </p>
+ * <p>
  * The use of FastHashMap is deprecated and will be replaced in a future
- * release. </p>
+ * release.
+ * </p>
  */
 //TODO mutable non-private fields
 public class Form implements Serializable {
@@ -72,24 +73,6 @@
     private boolean processed;
 
     /**
-     * Gets the name/key of the set of validation rules.
-     *
-     * @return   The name value
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Sets the name/key of the set of validation rules.
-     *
-     * @param name  The new name value
-     */
-    public void setName(final String name) {
-        this.name = name;
-    }
-
-    /**
      * Add a <code>Field</code> to the <code>Form</code>.
      *
      * @param f  The field
@@ -100,13 +83,24 @@
     }
 
     /**
-     * A <code>List</code> of <code>Field</code>s is returned as an unmodifiable
-     * <code>List</code>.
+     * Returns true if this Form contains a Field with the given name.
      *
-     * @return   The fields value
+     * @param fieldName  The field name
+     * @return           True if this form contains the field by the given name
+     * @since 1.1
      */
-    public List<Field> getFields() {
-        return Collections.unmodifiableList(lFields);
+    public boolean containsField(final String fieldName) {
+        return getFieldMap().containsKey(fieldName);
+    }
+
+    /**
+     * Gets the name/key of the parent set of validation rules.
+     *
+     * @return   The extends value
+     * @since 1.2.0
+     */
+    public String getExtends() {
+        return inherit;
     }
 
     /**
@@ -122,14 +116,54 @@
     }
 
     /**
-     * Returns true if this Form contains a Field with the given name.
+     * Returns a Map of String field keys to Field objects.
      *
-     * @param fieldName  The field name
-     * @return           True if this form contains the field by the given name
-     * @since 1.1
+     * @return   The fieldMap value
+     * @since 1.2.0
      */
-    public boolean containsField(final String fieldName) {
-        return getFieldMap().containsKey(fieldName);
+    @SuppressWarnings("unchecked") // FastHashMap is not generic
+    protected Map<String, Field> getFieldMap() {
+        return hFields;
+    }
+
+    /**
+     * A <code>List</code> of <code>Field</code>s is returned as an unmodifiable
+     * <code>List</code>.
+     *
+     * @return   The fields value
+     */
+    public List<Field> getFields() {
+        return Collections.unmodifiableList(lFields);
+    }
+
+    /**
+     * Gets the name/key of the set of validation rules.
+     *
+     * @return   The name value
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Gets extends flag.
+     *
+     * @return   The extending value
+     * @since 1.2.0
+     */
+    public boolean isExtending() {
+        return inherit != null;
+    }
+
+    /**
+     * Whether or not the this <code>Form</code> was processed for replacing
+     * variables in strings with their values.
+     *
+     * @return   The processed value
+     * @since 1.2.0
+     */
+    public boolean isProcessed() {
+        return processed;
     }
 
     /**
@@ -208,6 +242,25 @@
     }
 
     /**
+     * Sets the name/key of the parent set of validation rules.
+     *
+     * @param inherit  The new extends value
+     * @since 1.2.0
+     */
+    public void setExtends(final String inherit) {
+        this.inherit = inherit;
+    }
+
+    /**
+     * Sets the name/key of the set of validation rules.
+     *
+     * @param name  The new name value
+     */
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
      * Returns a string representation of the object.
      *
      * @return string representation
@@ -262,7 +315,7 @@
      * @since 1.2.0
      */
     ValidatorResults validate(final Map<String, Object> params, final Map<String, ValidatorAction> actions, final int page, final String fieldName)
-        throws ValidatorException {
+            throws ValidatorException {
         final ValidatorResults results = new ValidatorResults();
         params.put(Validator.VALIDATOR_RESULTS_PARAM, results);
 
@@ -271,12 +324,12 @@
             final Field field = getFieldMap().get(fieldName);
 
             if (field == null) {
-               throw new ValidatorException("Unknown field "+fieldName+" in form "+getName());
+                throw new ValidatorException("Unknown field " + fieldName + " in form " + getName());
             }
             params.put(Validator.FIELD_PARAM, field);
 
             if (field.getPage() <= page) {
-               results.merge(field.validate(params, actions));
+                results.merge(field.validate(params, actions));
             }
         } else {
             for (final Field field : this.lFields) {
@@ -291,56 +344,4 @@
 
         return results;
     }
-
-    /**
-     * Whether or not the this <code>Form</code> was processed for replacing
-     * variables in strings with their values.
-     *
-     * @return   The processed value
-     * @since 1.2.0
-     */
-    public boolean isProcessed() {
-        return processed;
-    }
-
-    /**
-     * Gets the name/key of the parent set of validation rules.
-     *
-     * @return   The extends value
-     * @since 1.2.0
-     */
-    public String getExtends() {
-        return inherit;
-    }
-
-    /**
-     * Sets the name/key of the parent set of validation rules.
-     *
-     * @param inherit  The new extends value
-     * @since 1.2.0
-     */
-    public void setExtends(final String inherit) {
-        this.inherit = inherit;
-    }
-
-    /**
-     * Get extends flag.
-     *
-     * @return   The extending value
-     * @since 1.2.0
-     */
-    public boolean isExtending() {
-        return inherit != null;
-    }
-
-    /**
-     * Returns a Map of String field keys to Field objects.
-     *
-     * @return   The fieldMap value
-     * @since 1.2.0
-     */
-    @SuppressWarnings("unchecked") // FastHashMap is not generic
-    protected Map<String, Field> getFieldMap() {
-        return hFields;
-    }
 }
diff --git a/src/main/java/org/apache/commons/validator/FormSet.java b/src/main/java/org/apache/commons/validator/FormSet.java
index 825b052..ffa73c2 100644
--- a/src/main/java/org/apache/commons/validator/FormSet.java
+++ b/src/main/java/org/apache/commons/validator/FormSet.java
@@ -34,6 +34,28 @@
 
     private static final long serialVersionUID = -8936513232763306055L;
 
+    /**
+     * This is the type of <code>FormSet</code>s where no locale is specified.
+     */
+    protected final static int GLOBAL_FORMSET = 1;
+
+    /**
+     * This is the type of <code>FormSet</code>s where only language locale is
+     * specified.
+     */
+    protected final static int LANGUAGE_FORMSET = 2;
+
+    /**
+     * This is the type of <code>FormSet</code>s where only language and country
+     * locale are specified.
+     */
+    protected final static int COUNTRY_FORMSET = 3;
+
+    /**
+     * This is the type of <code>FormSet</code>s where full locale has been set.
+     */
+    protected final static int VARIANT_FORMSET = 4;
+
     /** Logging */
     private transient Log log = LogFactory.getLog(FormSet.class);
 
@@ -65,182 +87,23 @@
     private final Map<String, String> constants = new HashMap<>();
 
     /**
-     * This is the type of <code>FormSet</code>s where no locale is specified.
-     */
-    protected final static int GLOBAL_FORMSET = 1;
-
-    /**
-     * This is the type of <code>FormSet</code>s where only language locale is
-     * specified.
-     */
-    protected final static int LANGUAGE_FORMSET = 2;
-
-    /**
-     * This is the type of <code>FormSet</code>s where only language and country
-     * locale are specified.
-     */
-    protected final static int COUNTRY_FORMSET = 3;
-
-    /**
-     * This is the type of <code>FormSet</code>s where full locale has been set.
-     */
-    protected final static int VARIANT_FORMSET = 4;
-
-    /**
      * Flag indicating if this formSet has been merged with its parent (higher
      * rank in Locale hierarchy).
      */
     private boolean merged;
 
     /**
-     * Has this formSet been merged?
-     *
-     * @return   true if it has been merged
-     * @since 1.2.0
-     */
-    protected boolean isMerged() {
-        return merged;
-    }
-
-    /**
-     * Returns the type of <code>FormSet</code>:<code>GLOBAL_FORMSET</code>,
-     * <code>LANGUAGE_FORMSET</code>,<code>COUNTRY_FORMSET</code> or <code>VARIANT_FORMSET</code>
-     * .
-     *
-     * @return                       The type value
-     * @since 1.2.0
-     * @throws NullPointerException  if there is inconsistency in the locale
-     *      definition (not sure about this)
-     */
-    protected int getType() {
-        if (getVariant() != null) {
-            if (getLanguage() == null || getCountry() == null) {
-                throw new NullPointerException(
-                    "When variant is specified, country and language must be specified.");
-            }
-            return VARIANT_FORMSET;
-        }
-        if (getCountry() != null) {
-            if (getLanguage() == null) {
-                throw new NullPointerException(
-                    "When country is specified, language must be specified.");
-            }
-            return COUNTRY_FORMSET;
-        }
-        if (getLanguage() != null) {
-            return LANGUAGE_FORMSET;
-        }
-        return GLOBAL_FORMSET;
-    }
-
-    /**
-     * Merges the given <code>FormSet</code> into this one. If any of <code>depends</code>
-     * s <code>Forms</code> are not in this <code>FormSet</code> then, include
-     * them, else merge both <code>Forms</code>. Theoretically we should only
-     * merge a "parent" formSet.
-     *
-     * @param depends  FormSet to be merged
-     * @since 1.2.0
-     */
-    protected void merge(final FormSet depends) {
-        if (depends != null) {
-            final Map<String, Form> pForms = getForms();
-            final Map<String, Form> dForms = depends.getForms();
-            for (final Entry<String, Form> entry : dForms.entrySet()) {
-                final String key = entry.getKey();
-                final Form pForm = pForms.get(key);
-                if (pForm != null) {//merge, but principal 'rules', don't overwrite
-                    // anything
-                    pForm.merge(entry.getValue());
-                }
-                else {//just add
-                    addForm(entry.getValue());
-                }
-            }
-        }
-        merged = true;
-    }
-
-    /**
-     * Whether or not the this <code>FormSet</code> was processed for replacing
-     * variables in strings with their values.
-     *
-     * @return   The processed value
-     */
-    public boolean isProcessed() {
-        return processed;
-    }
-
-    /**
-     * Gets the equivalent of the language component of <code>Locale</code>.
-     *
-     * @return   The language value
-     */
-    public String getLanguage() {
-        return language;
-    }
-
-    /**
-     * Sets the equivalent of the language component of <code>Locale</code>.
-     *
-     * @param language  The new language value
-     */
-    public void setLanguage(final String language) {
-        this.language = language;
-    }
-
-    /**
-     * Gets the equivalent of the country component of <code>Locale</code>.
-     *
-     * @return   The country value
-     */
-    public String getCountry() {
-        return country;
-    }
-
-    /**
-     * Sets the equivalent of the country component of <code>Locale</code>.
-     *
-     * @param country  The new country value
-     */
-    public void setCountry(final String country) {
-        this.country = country;
-    }
-
-    /**
-     * Gets the equivalent of the variant component of <code>Locale</code>.
-     *
-     * @return   The variant value
-     */
-    public String getVariant() {
-        return variant;
-    }
-
-    /**
-     * Sets the equivalent of the variant component of <code>Locale</code>.
-     *
-     * @param variant  The new variant value
-     */
-    public void setVariant(final String variant) {
-        this.variant = variant;
-    }
-
-    /**
      * Add a <code>Constant</code> to the locale level.
      *
      * @param name   The constant name
      * @param value  The constant value
      */
     public void addConstant(final String name, final String value) {
-
         if (constants.containsKey(name)) {
-            getLog().error("Constant '" + name +  "' already exists in FormSet["
-                      + this.displayKey() + "] - ignoring.");
-
+            getLog().error("Constant '" + name + "' already exists in FormSet[" + this.displayKey() + "] - ignoring.");
         } else {
             constants.put(name, value);
         }
-
     }
 
     /**
@@ -252,8 +115,7 @@
 
         final String formName = f.getName();
         if (forms.containsKey(formName)) {
-            getLog().error("Form '" + formName + "' already exists in FormSet["
-                      + this.displayKey() + "] - ignoring.");
+            getLog().error("Form '" + formName + "' already exists in FormSet[" + this.displayKey() + "] - ignoring.");
 
         } else {
             forms.put(f.getName(), f);
@@ -262,6 +124,47 @@
     }
 
     /**
+     * Returns a string representation of the object's key.
+     *
+     * @return   A string representation of the key
+     */
+    public String displayKey() {
+        final StringBuilder results = new StringBuilder();
+        if (language != null && !language.isEmpty()) {
+            results.append("language=");
+            results.append(language);
+        }
+        if (country != null && !country.isEmpty()) {
+            if (results.length() > 0) {
+                results.append(", ");
+            }
+            results.append("country=");
+            results.append(country);
+        }
+        if (variant != null && !variant.isEmpty()) {
+            if (results.length() > 0) {
+                results.append(", ");
+            }
+            results.append("variant=");
+            results.append(variant);
+        }
+        if (results.length() == 0) {
+            results.append("default");
+        }
+
+        return results.toString();
+    }
+
+    /**
+     * Gets the equivalent of the country component of <code>Locale</code>.
+     *
+     * @return   The country value
+     */
+    public String getCountry() {
+        return country;
+    }
+
+    /**
      * Retrieve a <code>Form</code> based on the form name.
      *
      * @param formName  The form name
@@ -282,6 +185,117 @@
     }
 
     /**
+     * Gets the equivalent of the language component of <code>Locale</code>.
+     *
+     * @return   The language value
+     */
+    public String getLanguage() {
+        return language;
+    }
+
+    /**
+     * Accessor method for Log instance.
+     *
+     * The Log instance variable is transient and
+     * accessing it through this method ensures it
+     * is re-initialized when this instance is
+     * de-serialized.
+     *
+     * @return The Log instance.
+     */
+    private Log getLog() {
+        if (log == null) {
+            log = LogFactory.getLog(FormSet.class);
+        }
+        return log;
+    }
+
+    /**
+     * Returns the type of <code>FormSet</code>:<code>GLOBAL_FORMSET</code>,
+     * <code>LANGUAGE_FORMSET</code>,<code>COUNTRY_FORMSET</code> or <code>VARIANT_FORMSET</code>
+     * .
+     *
+     * @return                       The type value
+     * @since 1.2.0
+     * @throws NullPointerException  if there is inconsistency in the locale
+     *      definition (not sure about this)
+     */
+    protected int getType() {
+        if (getVariant() != null) {
+            if (getLanguage() == null || getCountry() == null) {
+                throw new NullPointerException("When variant is specified, country and language must be specified.");
+            }
+            return VARIANT_FORMSET;
+        }
+        if (getCountry() != null) {
+            if (getLanguage() == null) {
+                throw new NullPointerException("When country is specified, language must be specified.");
+            }
+            return COUNTRY_FORMSET;
+        }
+        if (getLanguage() != null) {
+            return LANGUAGE_FORMSET;
+        }
+        return GLOBAL_FORMSET;
+    }
+
+    /**
+     * Gets the equivalent of the variant component of <code>Locale</code>.
+     *
+     * @return   The variant value
+     */
+    public String getVariant() {
+        return variant;
+    }
+
+    /**
+     * Has this formSet been merged?
+     *
+     * @return   true if it has been merged
+     * @since 1.2.0
+     */
+    protected boolean isMerged() {
+        return merged;
+    }
+
+    /**
+     * Whether or not the this <code>FormSet</code> was processed for replacing
+     * variables in strings with their values.
+     *
+     * @return   The processed value
+     */
+    public boolean isProcessed() {
+        return processed;
+    }
+
+    /**
+     * Merges the given <code>FormSet</code> into this one. If any of <code>depends</code>
+     * s <code>Forms</code> are not in this <code>FormSet</code> then, include
+     * them, else merge both <code>Forms</code>. Theoretically we should only
+     * merge a "parent" formSet.
+     *
+     * @param depends  FormSet to be merged
+     * @since 1.2.0
+     */
+    protected void merge(final FormSet depends) {
+        if (depends != null) {
+            final Map<String, Form> pForms = getForms();
+            final Map<String, Form> dForms = depends.getForms();
+            for (final Entry<String, Form> entry : dForms.entrySet()) {
+                final String key = entry.getKey();
+                final Form pForm = pForms.get(key);
+                if (pForm != null) { // merge, but principal 'rules', don't overwrite
+                    // anything
+                    pForm.merge(entry.getValue());
+                } else { // just add
+                    addForm(entry.getValue());
+                }
+            }
+        }
+        merged = true;
+    }
+
+    /**
      * Processes all of the <code>Form</code>s.
      *
      * @param globalConstants  Global constants
@@ -295,35 +309,30 @@
     }
 
     /**
-     * Returns a string representation of the object's key.
+     * Sets the equivalent of the country component of <code>Locale</code>.
      *
-     * @return   A string representation of the key
+     * @param country  The new country value
      */
-    public String displayKey() {
-        final StringBuilder results = new StringBuilder();
-        if (language != null && !language.isEmpty()) {
-            results.append("language=");
-            results.append(language);
-        }
-        if (country != null && !country.isEmpty()) {
-            if (results.length() > 0) {
-               results.append(", ");
-            }
-            results.append("country=");
-            results.append(country);
-        }
-        if (variant != null && !variant.isEmpty()) {
-            if (results.length() > 0) {
-               results.append(", ");
-            }
-            results.append("variant=");
-            results.append(variant );
-        }
-        if (results.length() == 0) {
-           results.append("default");
-        }
+    public void setCountry(final String country) {
+        this.country = country;
+    }
 
-        return results.toString();
+    /**
+     * Sets the equivalent of the language component of <code>Locale</code>.
+     *
+     * @param language  The new language value
+     */
+    public void setLanguage(final String language) {
+        this.language = language;
+    }
+
+    /**
+     * Sets the equivalent of the variant component of <code>Locale</code>.
+     *
+     * @param variant  The new variant value
+     */
+    public void setVariant(final String variant) {
+        this.variant = variant;
     }
 
     /**
@@ -351,21 +360,4 @@
 
         return results.toString();
     }
-
-    /**
-     * Accessor method for Log instance.
-     *
-     * The Log instance variable is transient and
-     * accessing it through this method ensures it
-     * is re-initialized when this instance is
-     * de-serialized.
-     *
-     * @return The Log instance.
-     */
-    private Log getLog() {
-        if (log == null) {
-            log =  LogFactory.getLog(FormSet.class);
-        }
-        return log;
-    }
 }
diff --git a/src/main/java/org/apache/commons/validator/FormSetFactory.java b/src/main/java/org/apache/commons/validator/FormSetFactory.java
index 763d62b..a69cf5a 100644
--- a/src/main/java/org/apache/commons/validator/FormSetFactory.java
+++ b/src/main/java/org/apache/commons/validator/FormSetFactory.java
@@ -32,27 +32,6 @@
     private transient Log log = LogFactory.getLog(FormSetFactory.class);
 
     /**
-     * <p>Create or retrieve a <code>FormSet</code> for the specified
-     *    attributes.</p>
-     *
-     * @param attributes The sax attributes for the formset element.
-     * @return The FormSet for a locale.
-     * @throws Exception If an error occurs creating the FormSet.
-     */
-    @Override
-    public Object createObject(final Attributes attributes) throws Exception {
-
-        final ValidatorResources resources = (ValidatorResources)digester.peek(0);
-
-        final String language = attributes.getValue("language");
-        final String country  = attributes.getValue("country");
-        final String variant  = attributes.getValue("variant");
-
-        return createFormSet(resources, language, country, variant);
-
-    }
-
-    /**
      * <p>Create or retrieve a <code>FormSet</code> based on the language, country
      *    and variant.</p>
      *
@@ -66,7 +45,7 @@
     private FormSet createFormSet(final ValidatorResources resources,
                                   final String language,
                                   final String country,
-                                  final String variant) throws Exception {
+                                  final String variant) {
 
         // Retrieve existing FormSet for the language/country/variant
         FormSet formSet = resources.getFormSet(language, country, variant);
@@ -95,6 +74,27 @@
     }
 
     /**
+     * <p>Create or retrieve a <code>FormSet</code> for the specified
+     *    attributes.</p>
+     *
+     * @param attributes The sax attributes for the formset element.
+     * @return The FormSet for a locale.
+     * @throws Exception If an error occurs creating the FormSet.
+     */
+    @Override
+    public Object createObject(final Attributes attributes) throws Exception {
+
+        final ValidatorResources resources = (ValidatorResources) digester.peek(0);
+
+        final String language = attributes.getValue("language");
+        final String country = attributes.getValue("country");
+        final String variant = attributes.getValue("variant");
+
+        return createFormSet(resources, language, country, variant);
+
+    }
+
+    /**
      * Accessor method for Log instance.
      *
      * The Log instance variable is transient and
@@ -106,7 +106,7 @@
      */
     private Log getLog() {
         if (log == null) {
-            log =  LogFactory.getLog(FormSetFactory.class);
+            log = LogFactory.getLog(FormSetFactory.class);
         }
         return log;
     }
diff --git a/src/main/java/org/apache/commons/validator/GenericTypeValidator.java b/src/main/java/org/apache/commons/validator/GenericTypeValidator.java
index 40f17d6..900fb96 100644
--- a/src/main/java/org/apache/commons/validator/GenericTypeValidator.java
+++ b/src/main/java/org/apache/commons/validator/GenericTypeValidator.java
@@ -91,18 +91,137 @@
     }
 
     /**
-     * Checks if the value can safely be converted to a short primitive.
+     * Checks if the field is a valid credit card number.
+     *
+     * <p>Reference Sean M. Burke's <a href="http://www.ling.nwu.edu/~sburke/pub/luhn_lib.pl">
+     * script</a>.</p>
      *
      * @param value The value validation is being performed on.
-     * @return the converted Short value.
+     * @return the converted Credit Card number.
      */
-    public static Short formatShort(final String value) {
+    public static Long formatCreditCard(final String value) {
+        return GenericValidator.isCreditCard(value) ? Long.valueOf(value) : null;
+    }
+
+    /**
+     * Checks if the field is a valid date.
+     *
+     * <p>The {@code Locale} is used with {@link java.text.DateFormat}. The {@link java.text.DateFormat#setLenient(boolean)}
+     * method is set to {@code false} for all.
+     * </p>
+     *
+     * @param value  The value validation is being performed on.
+     * @param locale The Locale to use to parse the date (system default if null)
+     * @return the converted Date value.
+     */
+    public static Date formatDate(final String value, final Locale locale) {
+        Date date = null;
+
         if (value == null) {
             return null;
         }
 
         try {
-            return Short.valueOf(value);
+            // Get the formatters to check against
+            DateFormat formatterShort = null;
+            DateFormat formatterDefault = null;
+            if (locale != null) {
+                formatterShort =
+                        DateFormat.getDateInstance(DateFormat.SHORT, locale);
+                formatterDefault =
+                        DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
+            } else {
+                formatterShort =
+                        DateFormat.getDateInstance(
+                                DateFormat.SHORT,
+                                Locale.getDefault());
+                formatterDefault =
+                        DateFormat.getDateInstance(
+                                DateFormat.DEFAULT,
+                                Locale.getDefault());
+            }
+
+            // Turn off lenient parsing
+            formatterShort.setLenient(false);
+            formatterDefault.setLenient(false);
+
+            // Firstly, try with the short form
+            try {
+                date = formatterShort.parse(value);
+            } catch (final ParseException e) {
+                // Fall back on the default one
+                date = formatterDefault.parse(value);
+            }
+        } catch (final ParseException e) {
+            // Bad date, so LOG and return null
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Date parse failed value=[" + value + "], " +
+                        "locale=[" + locale + "] " + e);
+            }
+        }
+
+        return date;
+    }
+
+    /**
+     * Checks if the field is a valid date.
+     *
+     * <p>The pattern is used with {@link java.text.SimpleDateFormat}.
+     * If strict is true, then the length will be checked so '2/12/1999' will
+     * not pass validation with the format 'MM/dd/yyyy' because the month isn't
+     * two digits. The {@link java.text.SimpleDateFormat#setLenient(boolean)}
+     * method is set to {@code false} for all.
+     * </p>
+     *
+     * @param value       The value validation is being performed on.
+     * @param datePattern The pattern passed to {@code SimpleDateFormat}.
+     * @param strict      Whether or not to have an exact match of the
+     *                    datePattern.
+     * @return the converted Date value.
+     */
+    public static Date formatDate(final String value, final String datePattern, final boolean strict) {
+        Date date = null;
+
+        if (value == null
+                || datePattern == null
+                || datePattern.isEmpty()) {
+            return null;
+        }
+
+        try {
+            final SimpleDateFormat formatter = new SimpleDateFormat(datePattern);
+            formatter.setLenient(false);
+
+            date = formatter.parse(value);
+
+            if (strict && datePattern.length() != value.length()) {
+                date = null;
+            }
+        } catch (final ParseException e) {
+            // Bad date so return null
+            if (LOG.isDebugEnabled()) {
+                LOG.debug("Date parse failed value=[" + value + "], " +
+                        "pattern=[" + datePattern + "], " +
+                        "strict=[" + strict + "] " + e);
+            }
+        }
+
+        return date;
+    }
+
+    /**
+     * Checks if the value can safely be converted to a double primitive.
+     *
+     * @param value The value validation is being performed on.
+     * @return the converted Double value.
+     */
+    public static Double formatDouble(final String value) {
+        if (value == null) {
+            return null;
+        }
+
+        try {
+            return Double.valueOf(value);
         } catch (final NumberFormatException e) {
             return null;
         }
@@ -110,32 +229,82 @@
     }
 
     /**
-     * Checks if the value can safely be converted to a short primitive.
+     * Checks if the value can safely be converted to a double primitive.
      *
      * @param value  The value validation is being performed on.
      * @param locale The locale to use to parse the number (system default if
      *               null)
-     * @return the converted Short value.
+     * @return the converted Double value.
      */
-    public static Short formatShort(final String value, final Locale locale) {
-        Short result = null;
+    public static Double formatDouble(final String value, final Locale locale) {
+        Double result = null;
 
         if (value != null) {
             NumberFormat formatter = null;
             if (locale != null) {
-                formatter = NumberFormat.getNumberInstance(locale);
+                formatter = NumberFormat.getInstance(locale);
             } else {
-                formatter = NumberFormat.getNumberInstance(Locale.getDefault());
+                formatter = NumberFormat.getInstance(Locale.getDefault());
             }
-            formatter.setParseIntegerOnly(true);
             final ParsePosition pos = new ParsePosition(0);
             final Number num = formatter.parse(value, pos);
 
             // If there was no error      and we used the whole string
             if (pos.getErrorIndex() == -1 && pos.getIndex() == value.length() &&
-                    num.doubleValue() >= Short.MIN_VALUE &&
-                    num.doubleValue() <= Short.MAX_VALUE) {
-                result = Short.valueOf(num.shortValue());
+                    num.doubleValue() >= Double.MAX_VALUE * -1 &&
+                    num.doubleValue() <= Double.MAX_VALUE) {
+                result = Double.valueOf(num.doubleValue());
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * Checks if the value can safely be converted to a float primitive.
+     *
+     * @param value The value validation is being performed on.
+     * @return the converted Float value.
+     */
+    public static Float formatFloat(final String value) {
+        if (value == null) {
+            return null;
+        }
+
+        try {
+            return Float.valueOf(value);
+        } catch (final NumberFormatException e) {
+            return null;
+        }
+
+    }
+
+    /**
+     * Checks if the value can safely be converted to a float primitive.
+     *
+     * @param value  The value validation is being performed on.
+     * @param locale The locale to use to parse the number (system default if
+     *               null)
+     * @return the converted Float value.
+     */
+    public static Float formatFloat(final String value, final Locale locale) {
+        Float result = null;
+
+        if (value != null) {
+            NumberFormat formatter = null;
+            if (locale != null) {
+                formatter = NumberFormat.getInstance(locale);
+            } else {
+                formatter = NumberFormat.getInstance(Locale.getDefault());
+            }
+            final ParsePosition pos = new ParsePosition(0);
+            final Number num = formatter.parse(value, pos);
+
+            // If there was no error      and we used the whole string
+            if (pos.getErrorIndex() == -1 && pos.getIndex() == value.length() &&
+                    num.doubleValue() >= Float.MAX_VALUE * -1 &&
+                    num.doubleValue() <= Float.MAX_VALUE) {
+                result = Float.valueOf(num.floatValue());
             }
         }
 
@@ -247,18 +416,18 @@
     }
 
     /**
-     * Checks if the value can safely be converted to a float primitive.
+     * Checks if the value can safely be converted to a short primitive.
      *
      * @param value The value validation is being performed on.
-     * @return the converted Float value.
+     * @return the converted Short value.
      */
-    public static Float formatFloat(final String value) {
+    public static Short formatShort(final String value) {
         if (value == null) {
             return null;
         }
 
         try {
-            return Float.valueOf(value);
+            return Short.valueOf(value);
         } catch (final NumberFormatException e) {
             return null;
         }
@@ -266,206 +435,37 @@
     }
 
     /**
-     * Checks if the value can safely be converted to a float primitive.
+     * Checks if the value can safely be converted to a short primitive.
      *
      * @param value  The value validation is being performed on.
      * @param locale The locale to use to parse the number (system default if
      *               null)
-     * @return the converted Float value.
+     * @return the converted Short value.
      */
-    public static Float formatFloat(final String value, final Locale locale) {
-        Float result = null;
+    public static Short formatShort(final String value, final Locale locale) {
+        Short result = null;
 
         if (value != null) {
             NumberFormat formatter = null;
             if (locale != null) {
-                formatter = NumberFormat.getInstance(locale);
+                formatter = NumberFormat.getNumberInstance(locale);
             } else {
-                formatter = NumberFormat.getInstance(Locale.getDefault());
+                formatter = NumberFormat.getNumberInstance(Locale.getDefault());
             }
+            formatter.setParseIntegerOnly(true);
             final ParsePosition pos = new ParsePosition(0);
             final Number num = formatter.parse(value, pos);
 
             // If there was no error      and we used the whole string
             if (pos.getErrorIndex() == -1 && pos.getIndex() == value.length() &&
-                    num.doubleValue() >= (Float.MAX_VALUE * -1) &&
-                    num.doubleValue() <= Float.MAX_VALUE) {
-                result = Float.valueOf(num.floatValue());
+                    num.doubleValue() >= Short.MIN_VALUE &&
+                    num.doubleValue() <= Short.MAX_VALUE) {
+                result = Short.valueOf(num.shortValue());
             }
         }
 
         return result;
     }
 
-    /**
-     * Checks if the value can safely be converted to a double primitive.
-     *
-     * @param value The value validation is being performed on.
-     * @return the converted Double value.
-     */
-    public static Double formatDouble(final String value) {
-        if (value == null) {
-            return null;
-        }
-
-        try {
-            return Double.valueOf(value);
-        } catch (final NumberFormatException e) {
-            return null;
-        }
-
-    }
-
-    /**
-     * Checks if the value can safely be converted to a double primitive.
-     *
-     * @param value  The value validation is being performed on.
-     * @param locale The locale to use to parse the number (system default if
-     *               null)
-     * @return the converted Double value.
-     */
-    public static Double formatDouble(final String value, final Locale locale) {
-        Double result = null;
-
-        if (value != null) {
-            NumberFormat formatter = null;
-            if (locale != null) {
-                formatter = NumberFormat.getInstance(locale);
-            } else {
-                formatter = NumberFormat.getInstance(Locale.getDefault());
-            }
-            final ParsePosition pos = new ParsePosition(0);
-            final Number num = formatter.parse(value, pos);
-
-            // If there was no error      and we used the whole string
-            if (pos.getErrorIndex() == -1 && pos.getIndex() == value.length() &&
-                    num.doubleValue() >= (Double.MAX_VALUE * -1) &&
-                    num.doubleValue() <= Double.MAX_VALUE) {
-                result = Double.valueOf(num.doubleValue());
-            }
-        }
-
-        return result;
-    }
-
-    /**
-     * Checks if the field is a valid date.
-     *
-     * <p>The {@code Locale} is used with {@code java.text.DateFormat}. The {@link java.text.DateFormat#setLenient(boolean)}
-     * method is set to {@code false} for all.
-     * </p>
-     *
-     * @param value  The value validation is being performed on.
-     * @param locale The Locale to use to parse the date (system default if null)
-     * @return the converted Date value.
-     */
-    public static Date formatDate(final String value, final Locale locale) {
-        Date date = null;
-
-        if (value == null) {
-            return null;
-        }
-
-        try {
-            // Get the formatters to check against
-            DateFormat formatterShort = null;
-            DateFormat formatterDefault = null;
-            if (locale != null) {
-                formatterShort =
-                        DateFormat.getDateInstance(DateFormat.SHORT, locale);
-                formatterDefault =
-                        DateFormat.getDateInstance(DateFormat.DEFAULT, locale);
-            } else {
-                formatterShort =
-                        DateFormat.getDateInstance(
-                                DateFormat.SHORT,
-                                Locale.getDefault());
-                formatterDefault =
-                        DateFormat.getDateInstance(
-                                DateFormat.DEFAULT,
-                                Locale.getDefault());
-            }
-
-            // Turn off lenient parsing
-            formatterShort.setLenient(false);
-            formatterDefault.setLenient(false);
-
-            // Firstly, try with the short form
-            try {
-                date = formatterShort.parse(value);
-            } catch (final ParseException e) {
-                // Fall back on the default one
-                date = formatterDefault.parse(value);
-            }
-        } catch (final ParseException e) {
-            // Bad date, so LOG and return null
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("Date parse failed value=[" + value + "], " +
-                        "locale=[" + locale + "] " + e);
-            }
-        }
-
-        return date;
-    }
-
-    /**
-     * Checks if the field is a valid date.
-     *
-     * <p>The pattern is used with {@code java.text.SimpleDateFormat}.
-     * If strict is true, then the length will be checked so '2/12/1999' will
-     * not pass validation with the format 'MM/dd/yyyy' because the month isn't
-     * two digits. The {@link java.text.SimpleDateFormat#setLenient(boolean)}
-     * method is set to {@code false} for all.
-     * </p>
-     *
-     * @param value       The value validation is being performed on.
-     * @param datePattern The pattern passed to {@code SimpleDateFormat}.
-     * @param strict      Whether or not to have an exact match of the
-     *                    datePattern.
-     * @return the converted Date value.
-     */
-    public static Date formatDate(final String value, final String datePattern, final boolean strict) {
-        Date date = null;
-
-        if (value == null
-                || datePattern == null
-                || datePattern.isEmpty()) {
-            return null;
-        }
-
-        try {
-            final SimpleDateFormat formatter = new SimpleDateFormat(datePattern);
-            formatter.setLenient(false);
-
-            date = formatter.parse(value);
-
-            if (strict && datePattern.length() != value.length()) {
-                date = null;
-            }
-        } catch (final ParseException e) {
-            // Bad date so return null
-            if (LOG.isDebugEnabled()) {
-                LOG.debug("Date parse failed value=[" + value + "], " +
-                        "pattern=[" + datePattern + "], " +
-                        "strict=[" + strict + "] " + e);
-            }
-        }
-
-        return date;
-    }
-
-    /**
-     * Checks if the field is a valid credit card number.
-     *
-     * <p>Reference Sean M. Burke's <a href="http://www.ling.nwu.edu/~sburke/pub/luhn_lib.pl">
-     * script</a>.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @return the converted Credit Card number.
-     */
-    public static Long formatCreditCard(final String value) {
-        return GenericValidator.isCreditCard(value) ? Long.valueOf(value) : null;
-    }
-
 }
 
diff --git a/src/main/java/org/apache/commons/validator/GenericValidator.java b/src/main/java/org/apache/commons/validator/GenericValidator.java
index 9f1f5cb..6589bfe 100644
--- a/src/main/java/org/apache/commons/validator/GenericValidator.java
+++ b/src/main/java/org/apache/commons/validator/GenericValidator.java
@@ -44,280 +44,6 @@
         new CreditCardValidator();
 
     /**
-     * <p>Checks if the field isn't null and length of the field is greater
-     * than zero not including whitespace.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @return true if blank or null.
-     */
-    public static boolean isBlankOrNull(final String value) {
-        return value == null || value.trim().isEmpty();
-    }
-
-    /**
-     * <p>Checks if the value matches the regular expression.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param regexp The regular expression.
-     * @return true if matches the regular expression.
-     */
-    public static boolean matchRegexp(final String value, final String regexp) {
-        if (regexp == null || regexp.isEmpty()) {
-            return false;
-        }
-
-        return Pattern.matches(regexp, value);
-    }
-
-    /**
-     * <p>Checks if the value can safely be converted to a byte primitive.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @return true if the value can be converted to a Byte.
-     */
-    public static boolean isByte(final String value) {
-        return (GenericTypeValidator.formatByte(value) != null);
-    }
-
-    /**
-     * <p>Checks if the value can safely be converted to a short primitive.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @return true if the value can be converted to a Short.
-     */
-    public static boolean isShort(final String value) {
-        return (GenericTypeValidator.formatShort(value) != null);
-    }
-
-    /**
-     * <p>Checks if the value can safely be converted to a int primitive.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @return true if the value can be converted to an Integer.
-     */
-    public static boolean isInt(final String value) {
-        return (GenericTypeValidator.formatInt(value) != null);
-    }
-
-    /**
-     * <p>Checks if the value can safely be converted to a long primitive.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @return true if the value can be converted to a Long.
-     */
-    public static boolean isLong(final String value) {
-        return (GenericTypeValidator.formatLong(value) != null);
-    }
-
-    /**
-     * <p>Checks if the value can safely be converted to a float primitive.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @return true if the value can be converted to a Float.
-     */
-    public static boolean isFloat(final String value) {
-        return (GenericTypeValidator.formatFloat(value) != null);
-    }
-
-    /**
-     * <p>Checks if the value can safely be converted to a double primitive.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @return true if the value can be converted to a Double.
-     */
-    public static boolean isDouble(final String value) {
-        return (GenericTypeValidator.formatDouble(value) != null);
-    }
-
-    /**
-     * <p>Checks if the field is a valid date.  The <code>Locale</code> is
-     * used with <code>java.text.DateFormat</code>.  The setLenient method
-     * is set to <code>false</code> for all.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the date format, defaults to the
-     * system default if null.
-     * @return true if the value can be converted to a Date.
-     */
-    public static boolean isDate(final String value, final Locale locale) {
-        return DateValidator.getInstance().isValid(value, locale);
-    }
-
-    /**
-     * <p>Checks if the field is a valid date.  The pattern is used with
-     * <code>java.text.SimpleDateFormat</code>.  If strict is true, then the
-     * length will be checked so '2/12/1999' will not pass validation with
-     * the format 'MM/dd/yyyy' because the month isn't two digits.
-     * The setLenient method is set to <code>false</code> for all.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param datePattern The pattern passed to <code>SimpleDateFormat</code>.
-     * @param strict Whether or not to have an exact match of the datePattern.
-     * @return true if the value can be converted to a Date.
-     */
-    public static boolean isDate(final String value, final String datePattern, final boolean strict) {
-        // TODO method isValid() not yet supported in routines version
-        return org.apache.commons.validator.DateValidator.getInstance().isValid(value, datePattern, strict);
-    }
-
-    /**
-    * <p>Checks if a value is within a range (min &amp; max specified
-    * in the vars attribute).</p>
-    *
-    * @param value The value validation is being performed on.
-    * @param min The minimum value of the range.
-    * @param max The maximum value of the range.
-     * @return true if the value is in the specified range.
-    */
-    public static boolean isInRange(final byte value, final byte min, final byte max) {
-        return ((value >= min) && (value <= max));
-    }
-
-    /**
-     * <p>Checks if a value is within a range (min &amp; max specified
-     * in the vars attribute).</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value of the range.
-     * @param max The maximum value of the range.
-     * @return true if the value is in the specified range.
-     */
-    public static boolean isInRange(final int value, final int min, final int max) {
-        return ((value >= min) && (value <= max));
-    }
-
-    /**
-     * <p>Checks if a value is within a range (min &amp; max specified
-     * in the vars attribute).</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value of the range.
-     * @param max The maximum value of the range.
-     * @return true if the value is in the specified range.
-     */
-    public static boolean isInRange(final float value, final float min, final float max) {
-        return ((value >= min) && (value <= max));
-    }
-
-    /**
-     * <p>Checks if a value is within a range (min &amp; max specified
-     * in the vars attribute).</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value of the range.
-     * @param max The maximum value of the range.
-     * @return true if the value is in the specified range.
-     */
-    public static boolean isInRange(final short value, final short min, final short max) {
-        return ((value >= min) && (value <= max));
-    }
-
-    /**
-     * <p>Checks if a value is within a range (min &amp; max specified
-     * in the vars attribute).</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value of the range.
-     * @param max The maximum value of the range.
-     * @return true if the value is in the specified range.
-     */
-    public static boolean isInRange(final long value, final long min, final long max) {
-        return ((value >= min) && (value <= max));
-    }
-
-    /**
-     * <p>Checks if a value is within a range (min &amp; max specified
-     * in the vars attribute).</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value of the range.
-     * @param max The maximum value of the range.
-     * @return true if the value is in the specified range.
-     */
-    public static boolean isInRange(final double value, final double min, final double max) {
-        return ((value >= min) && (value <= max));
-    }
-
-    /**
-     * Checks if the field is a valid credit card number.
-     * @param value The value validation is being performed on.
-     * @return true if the value is valid Credit Card Number.
-     */
-    public static boolean isCreditCard(final String value) {
-        return CREDIT_CARD_VALIDATOR.isValid(value);
-    }
-
-    /**
-     * <p>Checks if a field has a valid e-mail address.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @return true if the value is valid Email Address.
-     */
-    public static boolean isEmail(final String value) {
-        return EmailValidator.getInstance().isValid(value);
-    }
-
-    /**
-     * <p>Checks if a field is a valid URL address.</p>
-     * If you need to modify what is considered valid then
-     * consider using the UrlValidator directly.
-     *
-     * @param value The value validation is being performed on.
-     * @return true if the value is valid Url.
-     */
-    public static boolean isUrl(final String value) {
-        return URL_VALIDATOR.isValid(value);
-    }
-
-    /**
-     * <p>Checks if the value's length is less than or equal to the max.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param max The maximum length.
-     * @return true if the value's length is less than the specified maximum.
-     */
-    public static boolean maxLength(final String value, final int max) {
-        return (value.length() <= max);
-    }
-
-    /**
-     * <p>Checks if the value's adjusted length is less than or equal to the max.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param max The maximum length.
-     * @param lineEndLength The length to use for line endings.
-     * @return true if the value's length is less than the specified maximum.
-     */
-    public static boolean maxLength(final String value, final int max, final int lineEndLength) {
-        final int adjustAmount = adjustForLineEnding(value, lineEndLength);
-        return ((value.length() + adjustAmount) <= max);
-    }
-
-    /**
-     * <p>Checks if the value's length is greater than or equal to the min.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum length.
-     * @return true if the value's length is more than the specified minimum.
-     */
-    public static boolean minLength(final String value, final int min) {
-        return (value.length() >= min);
-    }
-
-    /**
-     * <p>Checks if the value's adjusted length is greater than or equal to the min.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum length.
-     * @param lineEndLength The length to use for line endings.
-     * @return true if the value's length is more than the specified minimum.
-     */
-    public static boolean minLength(final String value, final int min, final int lineEndLength) {
-        final int adjustAmount = adjustForLineEnding(value, lineEndLength);
-        return ((value.length() + adjustAmount) >= min);
-    }
-
-    /**
      * Calculate an adjustment amount for line endings.
      *
      * See Bug 37962 for the rational behind this.
@@ -337,75 +63,257 @@
                 rCount++;
             }
         }
-        return ((nCount * lineEndLength) - (rCount + nCount));
-    }
-
-    // See http://issues.apache.org/bugzilla/show_bug.cgi?id=29015 WRT the "value" methods
-
-    /**
-     * <p>Checks if the value is greater than or equal to the min.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum numeric value.
-     * @return true if the value is &gt;= the specified minimum.
-     */
-    public static boolean minValue(final int value, final int min) {
-        return (value >= min);
+        return nCount * lineEndLength - (rCount + nCount);
     }
 
     /**
-     * <p>Checks if the value is greater than or equal to the min.</p>
+     * <p>Checks if the field isn't null and length of the field is greater
+     * than zero not including whitespace.</p>
      *
      * @param value The value validation is being performed on.
-     * @param min The minimum numeric value.
-     * @return true if the value is &gt;= the specified minimum.
+     * @return true if blank or null.
      */
-    public static boolean minValue(final long value, final long min) {
-        return (value >= min);
+    public static boolean isBlankOrNull(final String value) {
+        return value == null || value.trim().isEmpty();
     }
 
     /**
-     * <p>Checks if the value is greater than or equal to the min.</p>
+     * <p>Checks if the value can safely be converted to a byte primitive.</p>
      *
      * @param value The value validation is being performed on.
-     * @param min The minimum numeric value.
-     * @return true if the value is &gt;= the specified minimum.
+     * @return true if the value can be converted to a Byte.
      */
-    public static boolean minValue(final double value, final double min) {
-        return (value >= min);
+    public static boolean isByte(final String value) {
+        return GenericTypeValidator.formatByte(value) != null;
     }
 
     /**
-     * <p>Checks if the value is greater than or equal to the min.</p>
-     *
+     * Checks if the field is a valid credit card number.
      * @param value The value validation is being performed on.
-     * @param min The minimum numeric value.
-     * @return true if the value is &gt;= the specified minimum.
+     * @return true if the value is valid Credit Card Number.
      */
-    public static boolean minValue(final float value, final float min) {
-        return (value >= min);
+    public static boolean isCreditCard(final String value) {
+        return CREDIT_CARD_VALIDATOR.isValid(value);
     }
 
     /**
-     * <p>Checks if the value is less than or equal to the max.</p>
+     * <p>Checks if the field is a valid date.  The <code>Locale</code> is
+     * used with <code>java.text.DateFormat</code>.  The setLenient method
+     * is set to {@code false} for all.</p>
      *
      * @param value The value validation is being performed on.
-     * @param max The maximum numeric value.
-     * @return true if the value is &lt;= the specified maximum.
+     * @param locale The locale to use for the date format, defaults to the
+     * system default if null.
+     * @return true if the value can be converted to a Date.
      */
-    public static boolean maxValue(final int value, final int max) {
-        return (value <= max);
+    public static boolean isDate(final String value, final Locale locale) {
+        return DateValidator.getInstance().isValid(value, locale);
     }
 
     /**
-     * <p>Checks if the value is less than or equal to the max.</p>
+     * <p>Checks if the field is a valid date.  The pattern is used with
+     * <code>java.text.SimpleDateFormat</code>.  If strict is true, then the
+     * length will be checked so '2/12/1999' will not pass validation with
+     * the format 'MM/dd/yyyy' because the month isn't two digits.
+     * The setLenient method is set to {@code false} for all.</p>
      *
      * @param value The value validation is being performed on.
-     * @param max The maximum numeric value.
-     * @return true if the value is &lt;= the specified maximum.
+     * @param datePattern The pattern passed to <code>SimpleDateFormat</code>.
+     * @param strict Whether or not to have an exact match of the datePattern.
+     * @return true if the value can be converted to a Date.
      */
-    public static boolean maxValue(final long value, final long max) {
-        return (value <= max);
+    public static boolean isDate(final String value, final String datePattern, final boolean strict) {
+        // TODO method isValid() not yet supported in routines version
+        return org.apache.commons.validator.DateValidator.getInstance().isValid(value, datePattern, strict);
+    }
+
+    /**
+     * <p>Checks if the value can safely be converted to a double primitive.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @return true if the value can be converted to a Double.
+     */
+    public static boolean isDouble(final String value) {
+        return GenericTypeValidator.formatDouble(value) != null;
+    }
+
+    /**
+     * <p>Checks if a field has a valid e-mail address.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @return true if the value is valid Email Address.
+     */
+    public static boolean isEmail(final String value) {
+        return EmailValidator.getInstance().isValid(value);
+    }
+
+    /**
+     * <p>Checks if the value can safely be converted to a float primitive.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @return true if the value can be converted to a Float.
+     */
+    public static boolean isFloat(final String value) {
+        return GenericTypeValidator.formatFloat(value) != null;
+    }
+
+    /**
+    * <p>Checks if a value is within a range (min &amp; max specified
+    * in the vars attribute).</p>
+    *
+    * @param value The value validation is being performed on.
+    * @param min The minimum value of the range.
+    * @param max The maximum value of the range.
+     * @return true if the value is in the specified range.
+    */
+    public static boolean isInRange(final byte value, final byte min, final byte max) {
+        return value >= min && value <= max;
+    }
+
+    /**
+     * <p>Checks if a value is within a range (min &amp; max specified
+     * in the vars attribute).</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value of the range.
+     * @param max The maximum value of the range.
+     * @return true if the value is in the specified range.
+     */
+    public static boolean isInRange(final double value, final double min, final double max) {
+        return value >= min && value <= max;
+    }
+
+    /**
+     * <p>Checks if a value is within a range (min &amp; max specified
+     * in the vars attribute).</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value of the range.
+     * @param max The maximum value of the range.
+     * @return true if the value is in the specified range.
+     */
+    public static boolean isInRange(final float value, final float min, final float max) {
+        return value >= min && value <= max;
+    }
+
+    /**
+     * <p>Checks if a value is within a range (min &amp; max specified
+     * in the vars attribute).</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value of the range.
+     * @param max The maximum value of the range.
+     * @return true if the value is in the specified range.
+     */
+    public static boolean isInRange(final int value, final int min, final int max) {
+        return value >= min && value <= max;
+    }
+
+    /**
+     * <p>Checks if a value is within a range (min &amp; max specified
+     * in the vars attribute).</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value of the range.
+     * @param max The maximum value of the range.
+     * @return true if the value is in the specified range.
+     */
+    public static boolean isInRange(final long value, final long min, final long max) {
+        return value >= min && value <= max;
+    }
+
+    /**
+     * <p>Checks if a value is within a range (min &amp; max specified
+     * in the vars attribute).</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value of the range.
+     * @param max The maximum value of the range.
+     * @return true if the value is in the specified range.
+     */
+    public static boolean isInRange(final short value, final short min, final short max) {
+        return value >= min && value <= max;
+    }
+
+    /**
+     * <p>Checks if the value can safely be converted to a int primitive.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @return true if the value can be converted to an Integer.
+     */
+    public static boolean isInt(final String value) {
+        return GenericTypeValidator.formatInt(value) != null;
+    }
+
+    /**
+     * <p>Checks if the value can safely be converted to a long primitive.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @return true if the value can be converted to a Long.
+     */
+    public static boolean isLong(final String value) {
+        return GenericTypeValidator.formatLong(value) != null;
+    }
+
+    /**
+     * <p>Checks if the value can safely be converted to a short primitive.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @return true if the value can be converted to a Short.
+     */
+    public static boolean isShort(final String value) {
+        return GenericTypeValidator.formatShort(value) != null;
+    }
+
+    /**
+     * <p>Checks if a field is a valid URL address.</p>
+     * If you need to modify what is considered valid then
+     * consider using the UrlValidator directly.
+     *
+     * @param value The value validation is being performed on.
+     * @return true if the value is valid Url.
+     */
+    public static boolean isUrl(final String value) {
+        return URL_VALIDATOR.isValid(value);
+    }
+
+    /**
+     * <p>Checks if the value matches the regular expression.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param regexp The regular expression.
+     * @return true if matches the regular expression.
+     */
+    public static boolean matchRegexp(final String value, final String regexp) {
+        if (regexp == null || regexp.isEmpty()) {
+            return false;
+        }
+
+        return Pattern.matches(regexp, value);
+    }
+
+    /**
+     * <p>Checks if the value's length is less than or equal to the max.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param max The maximum length.
+     * @return true if the value's length is less than the specified maximum.
+     */
+    public static boolean maxLength(final String value, final int max) {
+        return value.length() <= max;
+    }
+
+    /**
+     * <p>Checks if the value's adjusted length is less than or equal to the max.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param max The maximum length.
+     * @param lineEndLength The length to use for line endings.
+     * @return true if the value's length is less than the specified maximum.
+     */
+    public static boolean maxLength(final String value, final int max, final int lineEndLength) {
+        final int adjustAmount = adjustForLineEnding(value, lineEndLength);
+        return value.length() + adjustAmount <= max;
     }
 
     /**
@@ -416,7 +324,7 @@
      * @return true if the value is &lt;= the specified maximum.
      */
     public static boolean maxValue(final double value, final double max) {
-        return (value <= max);
+        return value <= max;
     }
 
     /**
@@ -427,7 +335,99 @@
      * @return true if the value is &lt;= the specified maximum.
      */
     public static boolean maxValue(final float value, final float max) {
-        return (value <= max);
+        return value <= max;
+    }
+
+    // See https://issues.apache.org/bugzilla/show_bug.cgi?id=29015 WRT the "value" methods
+
+    /**
+     * <p>Checks if the value is less than or equal to the max.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param max The maximum numeric value.
+     * @return true if the value is &lt;= the specified maximum.
+     */
+    public static boolean maxValue(final int value, final int max) {
+        return value <= max;
+    }
+
+    /**
+     * <p>Checks if the value is less than or equal to the max.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param max The maximum numeric value.
+     * @return true if the value is &lt;= the specified maximum.
+     */
+    public static boolean maxValue(final long value, final long max) {
+        return value <= max;
+    }
+
+    /**
+     * <p>Checks if the value's length is greater than or equal to the min.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum length.
+     * @return true if the value's length is more than the specified minimum.
+     */
+    public static boolean minLength(final String value, final int min) {
+        return value.length() >= min;
+    }
+
+    /**
+     * <p>Checks if the value's adjusted length is greater than or equal to the min.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum length.
+     * @param lineEndLength The length to use for line endings.
+     * @return true if the value's length is more than the specified minimum.
+     */
+    public static boolean minLength(final String value, final int min, final int lineEndLength) {
+        final int adjustAmount = adjustForLineEnding(value, lineEndLength);
+        return value.length() + adjustAmount >= min;
+    }
+
+    /**
+     * <p>Checks if the value is greater than or equal to the min.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum numeric value.
+     * @return true if the value is &gt;= the specified minimum.
+     */
+    public static boolean minValue(final double value, final double min) {
+        return value >= min;
+    }
+
+    /**
+     * <p>Checks if the value is greater than or equal to the min.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum numeric value.
+     * @return true if the value is &gt;= the specified minimum.
+     */
+    public static boolean minValue(final float value, final float min) {
+        return value >= min;
+    }
+
+    /**
+     * <p>Checks if the value is greater than or equal to the min.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum numeric value.
+     * @return true if the value is &gt;= the specified minimum.
+     */
+    public static boolean minValue(final int value, final int min) {
+        return value >= min;
+    }
+
+    /**
+     * <p>Checks if the value is greater than or equal to the min.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum numeric value.
+     * @return true if the value is &gt;= the specified minimum.
+     */
+    public static boolean minValue(final long value, final long min) {
+        return value >= min;
     }
 
 }
diff --git a/src/main/java/org/apache/commons/validator/ISBNValidator.java b/src/main/java/org/apache/commons/validator/ISBNValidator.java
index 5cfeec4..665cd3b 100644
--- a/src/main/java/org/apache/commons/validator/ISBNValidator.java
+++ b/src/main/java/org/apache/commons/validator/ISBNValidator.java
@@ -43,7 +43,7 @@
      * divided by 11 according to the ISBN algorithm.  If the result is zero,
      * the ISBN is valid.  This method accepts formatted or raw ISBN codes.
      *
-     * @param isbn Candidate ISBN number to be validated. <code>null</code> is
+     * @param isbn Candidate ISBN number to be validated. {@code null} is
      * considered invalid.
      * @return true if the string is a valid ISBN code.
      */
diff --git a/src/main/java/org/apache/commons/validator/Msg.java b/src/main/java/org/apache/commons/validator/Msg.java
index 4cf10f1..f1e315e 100644
--- a/src/main/java/org/apache/commons/validator/Msg.java
+++ b/src/main/java/org/apache/commons/validator/Msg.java
@@ -55,6 +55,20 @@
     protected boolean resource = true;
 
     /**
+     * Creates and returns a copy of this object.
+     * @return A copy of the Msg.
+     */
+    @Override
+    public Object clone() {
+        try {
+            return super.clone();
+
+        } catch (final CloneNotSupportedException e) {
+            throw new UnsupportedOperationException(e.toString(), e);
+        }
+    }
+
+    /**
      * Returns the resource bundle name.
      * @return The bundle name.
      * @since 1.1
@@ -64,6 +78,31 @@
     }
 
     /**
+     * Gets the key/value.
+     * @return The message key/value.
+     */
+    public String getKey() {
+        return key;
+    }
+
+    /**
+     * Gets the name of the dependency.
+     * @return The dependency name.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Tests whether or not the key is a resource key or literal value.
+     * @return {@code true} if key is a resource key.
+     * @since 1.1.4
+     */
+    public boolean isResource() {
+        return this.resource;
+    }
+
+    /**
      * Sets the resource bundle name.
      * @param bundle The new bundle name.
      * @since 1.1
@@ -73,11 +112,11 @@
     }
 
     /**
-     * Gets the name of the dependency.
-     * @return The dependency name.
+     * Sets the key/value.
+     * @param key The message key/value.
      */
-    public String getName() {
-        return name;
+    public void setKey(final String key) {
+        this.key = key;
     }
 
     /**
@@ -89,31 +128,6 @@
     }
 
     /**
-     * Gets the key/value.
-     * @return The message key/value.
-     */
-    public String getKey() {
-        return key;
-    }
-
-    /**
-     * Sets the key/value.
-     * @param key The message key/value.
-     */
-    public void setKey(final String key) {
-        this.key = key;
-    }
-
-    /**
-     * Tests whether or not the key is a resource key or literal value.
-     * @return <code>true</code> if key is a resource key.
-     * @since 1.1.4
-     */
-    public boolean isResource() {
-        return this.resource;
-    }
-
-    /**
      * Sets whether or not the key is a resource.
      * @param resource If true indicates the key is a resource.
      * @since 1.1.4
@@ -123,20 +137,6 @@
     }
 
     /**
-     * Creates and returns a copy of this object.
-     * @return A copy of the Msg.
-     */
-    @Override
-    public Object clone() {
-        try {
-            return super.clone();
-
-        } catch(final CloneNotSupportedException e) {
-            throw new RuntimeException(e.toString());
-        }
-    }
-
-    /**
      * Returns a string representation of the object.
      * @return Msg String representation.
      */
diff --git a/src/main/java/org/apache/commons/validator/UrlValidator.java b/src/main/java/org/apache/commons/validator/UrlValidator.java
index f820e73..ee918ee 100644
--- a/src/main/java/org/apache/commons/validator/UrlValidator.java
+++ b/src/main/java/org/apache/commons/validator/UrlValidator.java
@@ -39,7 +39,7 @@
  * </ul>
  *
  * <p>Originally based in on php script by Debbie Dyer, validation.php v1.2b, Date: 03/07/02,
- * http://javascript.internet.com. However, this validation now bears little resemblance
+ * https://javascript.internet.com. However, this validation now bears little resemblance
  * to the php original.</p>
  * <pre>
  *   Example of usage:
@@ -190,6 +190,16 @@
     }
 
     /**
+     * Initialize a UrlValidator with the given validation options.
+     * @param options The options should be set using the public constants declared in
+     * this class.  To set multiple options you simply add them together.  For example,
+     * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options.
+     */
+    public UrlValidator(final int options) {
+        this(null, options);
+    }
+
+    /**
      * Behavior of validation is modified by passing in several strings options:
      * @param schemes Pass in one or more URL schemes to consider valid, passing in
      *        a null will default to "http,https,ftp" being valid.
@@ -202,16 +212,6 @@
     }
 
     /**
-     * Initialize a UrlValidator with the given validation options.
-     * @param options The options should be set using the public constants declared in
-     * this class.  To set multiple options you simply add them together.  For example,
-     * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options.
-     */
-    public UrlValidator(final int options) {
-        this(null, options);
-    }
-
-    /**
      * Behavour of validation is modified by passing in options:
      * @param schemes The set of valid schemes.
      * @param options The options should be set using the public constants declared in
@@ -233,9 +233,28 @@
     }
 
     /**
+     * Returns the number of times the token appears in the target.
+     * @param token Token value to be counted.
+     * @param target Target value to count tokens in.
+     * @return the number of tokens.
+     */
+    protected int countToken(final String token, final String target) {
+        int tokenIndex = 0;
+        int count = 0;
+        while (tokenIndex != -1) {
+            tokenIndex = target.indexOf(token, tokenIndex);
+            if (tokenIndex > -1) {
+                tokenIndex++;
+                count++;
+            }
+        }
+        return count;
+    }
+
+    /**
      * <p>Checks if a field has a valid URL address.</p>
      *
-     * @param value The value validation is being performed on.  A <code>null</code>
+     * @param value The value validation is being performed on.  A {@code null}
      * value is considered invalid.
      * @return true if the URL is valid.
      */
@@ -277,32 +296,8 @@
     }
 
     /**
-     * Validate scheme. If schemes[] was initialized to a non null,
-     * then only those scheme's are allowed.  Note this is slightly different
-     * than for the constructor.
-     * @param scheme The scheme to validate.  A <code>null</code> value is considered
-     * invalid.
-     * @return true if valid.
-     */
-    protected boolean isValidScheme(final String scheme) {
-        if (scheme == null) {
-            return false;
-        }
-
-        if (!SCHEME_PATTERN.matcher(scheme).matches()) {
-            return false;
-        }
-
-        if (options.isOff(ALLOW_ALL_SCHEMES) && !allowedSchemes.contains(scheme)) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
      * Returns true if the authority is properly formatted.  An authority is the combination
-     * of hostname and port.  A <code>null</code> authority value is considered invalid.
+     * of hostname and port.  A {@code null} authority value is considered invalid.
      * @param authority Authority value to validate.
      * @return true if authority (hostname and port) is valid.
      */
@@ -336,7 +331,7 @@
             final char[] chars = hostIP.toCharArray();
             int size = 1;
             for (final char element : chars) {
-                if(element == '.') {
+                if (element == '.') {
                     size++;
                 }
             }
@@ -352,7 +347,7 @@
                     domainSegment[segmentCount] = atomMatcher.group(1);
                     segmentLength = domainSegment[segmentCount].length() + 1;
                     hostIP =
-                            (segmentLength >= hostIP.length())
+                            segmentLength >= hostIP.length()
                             ? ""
                             : hostIP.substring(segmentLength);
 
@@ -393,7 +388,20 @@
     }
 
     /**
-     * Returns true if the path is valid.  A <code>null</code> value is considered invalid.
+     * Returns true if the given fragment is null or fragments are allowed.
+     * @param fragment Fragment value to validate.
+     * @return true if fragment is valid.
+     */
+    protected boolean isValidFragment(final String fragment) {
+        if (fragment == null) {
+            return true;
+        }
+
+        return options.isOff(NO_FRAGMENTS);
+    }
+
+    /**
+     * Returns true if the path is valid.  A {@code null} value is considered invalid.
      * @param path Path value to validate.
      * @return true if path is valid.
      */
@@ -407,13 +415,13 @@
         }
 
         final int slash2Count = countToken("//", path);
-        if (options.isOff(ALLOW_2_SLASHES) && (slash2Count > 0)) {
+        if (options.isOff(ALLOW_2_SLASHES) && slash2Count > 0) {
             return false;
         }
 
         final int slashCount = countToken("/", path);
         final int dot2Count = countToken("..", path);
-        if (dot2Count > 0 && (slashCount - slash2Count - 1) <= dot2Count){
+        if (dot2Count > 0 && slashCount - slash2Count - 1 <= dot2Count) {
             return false;
         }
 
@@ -434,34 +442,26 @@
     }
 
     /**
-     * Returns true if the given fragment is null or fragments are allowed.
-     * @param fragment Fragment value to validate.
-     * @return true if fragment is valid.
+     * Validate scheme. If schemes[] was initialized to a non null,
+     * then only those scheme's are allowed.  Note this is slightly different
+     * than for the constructor.
+     * @param scheme The scheme to validate.  A {@code null} value is considered
+     * invalid.
+     * @return true if valid.
      */
-    protected boolean isValidFragment(final String fragment) {
-        if (fragment == null) {
-            return true;
+    protected boolean isValidScheme(final String scheme) {
+        if (scheme == null) {
+            return false;
         }
 
-        return options.isOff(NO_FRAGMENTS);
-    }
-
-    /**
-     * Returns the number of times the token appears in the target.
-     * @param token Token value to be counted.
-     * @param target Target value to count tokens in.
-     * @return the number of tokens.
-     */
-    protected int countToken(final String token, final String target) {
-        int tokenIndex = 0;
-        int count = 0;
-        while (tokenIndex != -1) {
-            tokenIndex = target.indexOf(token, tokenIndex);
-            if (tokenIndex > -1) {
-                tokenIndex++;
-                count++;
-            }
+        if (!SCHEME_PATTERN.matcher(scheme).matches()) {
+            return false;
         }
-        return count;
+
+        if (options.isOff(ALLOW_ALL_SCHEMES) && !allowedSchemes.contains(scheme)) {
+            return false;
+        }
+
+        return true;
     }
 }
diff --git a/src/main/java/org/apache/commons/validator/Validator.java b/src/main/java/org/apache/commons/validator/Validator.java
index add20bc..7e91b00 100644
--- a/src/main/java/org/apache/commons/validator/Validator.java
+++ b/src/main/java/org/apache/commons/validator/Validator.java
@@ -124,17 +124,17 @@
 
     /**
      * Whether or not to use the Context ClassLoader when loading classes
-     * for instantiating new objects.  Default is <code>false</code>.
+     * for instantiating new objects.  Default is {@code false}.
      */
     protected boolean useContextClassLoader;
 
     /**
-     * Set this to true to not return Fields that pass validation.  Only return failures.
+     * Sets this to true to not return Fields that pass validation.  Only return failures.
      */
     protected boolean onlyReturnErrors;
 
     /**
-     * Construct a <code>Validator</code> that will
+     * Constructs a <code>Validator</code> that will
      * use the <code>ValidatorResources</code>
      * passed in to retrieve pluggable validators
      * the different sets of validation rules.
@@ -146,7 +146,7 @@
     }
 
     /**
-     * Construct a <code>Validator</code> that will
+     * Constructs a <code>Validator</code> that will
      * use the <code>ValidatorResources</code>
      * passed in to retrieve pluggable validators
      * the different sets of validation rules.
@@ -164,7 +164,7 @@
     }
 
     /**
-     * Construct a <code>Validator</code> that will
+     * Constructs a <code>Validator</code> that will
      * use the <code>ValidatorResources</code>
      * passed in to retrieve pluggable validators
      * the different sets of validation rules.
@@ -185,86 +185,6 @@
     }
 
     /**
-     * Set a parameter of a pluggable validation method.
-     *
-     * @param parameterClassName The full class name of the parameter of the
-     * validation method that corresponds to the value/instance passed in with it.
-     *
-     * @param parameterValue The instance that will be passed into the
-     * validation method.
-     */
-    public void setParameter(final String parameterClassName, final Object parameterValue) {
-        this.parameters.put(parameterClassName, parameterValue);
-    }
-
-    /**
-     * Returns the value of the specified parameter that will be used during the
-     * processing of validations.
-     *
-     * @param parameterClassName The full class name of the parameter of the
-     * validation method that corresponds to the value/instance passed in with it.
-     * @return value of the specified parameter.
-     */
-    public Object getParameterValue(final String parameterClassName) {
-        return this.parameters.get(parameterClassName);
-    }
-
-    /**
-     * Gets the form name which is the key to a set of validation rules.
-     * @return the name of the form.
-     */
-    public String getFormName() {
-        return formName;
-    }
-
-    /**
-     * Sets the form name which is the key to a set of validation rules.
-     * @param formName the name of the form.
-     */
-    public void setFormName(final String formName) {
-        this.formName = formName;
-    }
-
-    /**
-     * Sets the name of the field to validate in a form (optional)
-     *
-     * @param fieldName The name of the field in a form set
-     * @since 1.2.0
-     */
-    public void setFieldName(final String fieldName) {
-        this.fieldName = fieldName;
-    }
-
-    /**
-     * Gets the page.
-     *
-     * <p>
-     * This in conjunction with the page property of
-     * a {@code Field} can control the processing of fields. If the field's
-     * page is less than or equal to this page value, it will be processed.
-     * </p>
-     *
-     * @return the page number.
-     */
-    public int getPage() {
-        return page;
-    }
-
-    /**
-     * Sets the page.
-     * <p>
-     * This in conjunction with the page property of
-     * a {@code Field} can control the processing of fields. If the field's page
-     * is less than or equal to this page value, it will be processed.
-     * </p>
-     *
-     * @param page the page number.
-     */
-    public void setPage(final int page) {
-        this.page = page;
-    }
-
-    /**
      * Clears the form name, resources that were added, and the page that was
      * set (if any).  This can be called to reinitialize the Validator instance
      * so it can be reused.  The form name (key to set of validation rules) and any
@@ -281,28 +201,7 @@
     }
 
     /**
-     * Return the boolean as to whether the context classloader should be used.
-     * @return whether the context classloader should be used.
-     */
-    public boolean getUseContextClassLoader() {
-        return this.useContextClassLoader;
-    }
-
-    /**
-     * Determine whether to use the Context ClassLoader (the one found by
-     * calling <code>Thread.currentThread().getContextClassLoader()</code>)
-     * to resolve/load classes that are defined in various rules.  If not
-     * using Context ClassLoader, then the class-loading defaults to
-     * using the calling-class' ClassLoader.
-     *
-     * @param use determines whether to use Context ClassLoader.
-     */
-    public void setUseContextClassLoader(final boolean use) {
-        this.useContextClassLoader = use;
-    }
-
-    /**
-     * Return the class loader to be used for instantiating application objects
+     * Gets the class loader to be used for instantiating application objects
      * when required.  This is determined based upon the following rules:
      * <ul>
      * <li>The class loader set by <code>setClassLoader()</code>, if any</li>
@@ -328,10 +227,61 @@
     }
 
     /**
-     * Set the class loader to be used for instantiating application objects
+     * Gets the form name which is the key to a set of validation rules.
+     * @return the name of the form.
+     */
+    public String getFormName() {
+        return formName;
+    }
+
+    /**
+     * Returns true if the Validator is only returning Fields that fail validation.
+     * @return whether only failed fields are returned.
+     */
+    public boolean getOnlyReturnErrors() {
+        return onlyReturnErrors;
+    }
+
+    /**
+     * Gets the page.
+     *
+     * <p>
+     * This in conjunction with the page property of
+     * a {@code Field} can control the processing of fields. If the field's
+     * page is less than or equal to this page value, it will be processed.
+     * </p>
+     *
+     * @return the page number.
+     */
+    public int getPage() {
+        return page;
+    }
+
+    /**
+     * Returns the value of the specified parameter that will be used during the
+     * processing of validations.
+     *
+     * @param parameterClassName The full class name of the parameter of the
+     * validation method that corresponds to the value/instance passed in with it.
+     * @return value of the specified parameter.
+     */
+    public Object getParameterValue(final String parameterClassName) {
+        return this.parameters.get(parameterClassName);
+    }
+
+    /**
+     * Gets the boolean as to whether the context classloader should be used.
+     * @return whether the context classloader should be used.
+     */
+    public boolean getUseContextClassLoader() {
+        return this.useContextClassLoader;
+    }
+
+    /**
+     * Sets the class loader to be used for instantiating application objects
      * when required.
      *
-     * @param classLoader The new class loader to use, or <code>null</code>
+     * @param classLoader The new class loader to use, or {@code null}
      *  to revert to the standard rules
      */
     public void setClassLoader(final ClassLoader classLoader) {
@@ -339,6 +289,74 @@
     }
 
     /**
+     * Sets the name of the field to validate in a form (optional)
+     *
+     * @param fieldName The name of the field in a form set
+     * @since 1.2.0
+     */
+    public void setFieldName(final String fieldName) {
+        this.fieldName = fieldName;
+    }
+
+    /**
+     * Sets the form name which is the key to a set of validation rules.
+     * @param formName the name of the form.
+     */
+    public void setFormName(final String formName) {
+        this.formName = formName;
+    }
+
+    /**
+     * Configures which Fields the Validator returns from the validate() method.  Set this
+     * to true to only return Fields that failed validation.  By default, validate() returns
+     * all fields.
+     * @param onlyReturnErrors whether only failed fields are returned.
+     */
+    public void setOnlyReturnErrors(final boolean onlyReturnErrors) {
+        this.onlyReturnErrors = onlyReturnErrors;
+    }
+
+    /**
+     * Sets the page.
+     * <p>
+     * This in conjunction with the page property of
+     * a {@code Field} can control the processing of fields. If the field's page
+     * is less than or equal to this page value, it will be processed.
+     * </p>
+     *
+     * @param page the page number.
+     */
+    public void setPage(final int page) {
+        this.page = page;
+    }
+
+    /**
+     * Sets a parameter of a pluggable validation method.
+     *
+     * @param parameterClassName The full class name of the parameter of the
+     * validation method that corresponds to the value/instance passed in with it.
+     *
+     * @param parameterValue The instance that will be passed into the
+     * validation method.
+     */
+    public void setParameter(final String parameterClassName, final Object parameterValue) {
+        this.parameters.put(parameterClassName, parameterValue);
+    }
+
+    /**
+     * Determine whether to use the Context ClassLoader (the one found by
+     * calling <code>Thread.currentThread().getContextClassLoader()</code>)
+     * to resolve/load classes that are defined in various rules.  If not
+     * using Context ClassLoader, then the class-loading defaults to
+     * using the calling-class' ClassLoader.
+     *
+     * @param use determines whether to use Context ClassLoader.
+     */
+    public void setUseContextClassLoader(final boolean use) {
+        this.useContextClassLoader = use;
+    }
+
+    /**
      * Performs validations based on the configured resources.
      *
      * @return The <code>Map</code> returned uses the property of the
@@ -368,22 +386,4 @@
         return new ValidatorResults();
     }
 
-    /**
-     * Returns true if the Validator is only returning Fields that fail validation.
-     * @return whether only failed fields are returned.
-     */
-    public boolean getOnlyReturnErrors() {
-        return onlyReturnErrors;
-    }
-
-    /**
-     * Configures which Fields the Validator returns from the validate() method.  Set this
-     * to true to only return Fields that failed validation.  By default, validate() returns
-     * all fields.
-     * @param onlyReturnErrors whether only failed fields are returned.
-     */
-    public void setOnlyReturnErrors(final boolean onlyReturnErrors) {
-        this.onlyReturnErrors = onlyReturnErrors;
-    }
-
 }
diff --git a/src/main/java/org/apache/commons/validator/ValidatorAction.java b/src/main/java/org/apache/commons/validator/ValidatorAction.java
index eeb7087..6d1cfa0 100644
--- a/src/main/java/org/apache/commons/validator/ValidatorAction.java
+++ b/src/main/java/org/apache/commons/validator/ValidatorAction.java
@@ -24,6 +24,7 @@
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
@@ -35,9 +36,8 @@
 import org.apache.commons.validator.util.ValidatorUtils;
 
 /**
- * Contains the information to dynamically create and run a validation
- * method.  This is the class representation of a pluggable validator that can
- * be defined in an xml file with the &lt;validator&gt; element.
+ * Contains the information to dynamically create and run a validation method. This is the class representation of a pluggable validator that can be defined in
+ * an xml file with the &lt;validator&gt; element.
  *
  * <strong>Note</strong>: The validation method is assumed to be thread safe.
  */
@@ -56,47 +56,36 @@
     private String name;
 
     /**
-     * The full class name of the class containing
-     * the validation method associated with this action.
+     * The full class name of the class containing the validation method associated with this action.
      */
-    private String classname;
+    private String className;
 
     /**
-     * The Class object loaded from the classname.
+     * The Class object loaded from the class name.
      */
     private Class<?> validationClass;
 
     /**
-     * The full method name of the validation to be performed.  The method
-     * must be thread safe.
+     * The full method name of the validation to be performed. The method must be thread safe.
      */
     private String method;
 
     /**
      * The Method object loaded from the method name.
      */
-    private Method validationMethod;
+    private transient Method validationMethod;
 
     /**
      * <p>
-     * The method signature of the validation method.  This should be a comma
-     * delimited list of the full class names of each parameter in the correct
-     * order that the method takes.
+     * The method signature of the validation method. This should be a comma delimited list of the full class names of each parameter in the correct order that
+     * the method takes.
      * </p>
      * <p>
-     * Note: <code>java.lang.Object</code> is reserved for the
-     * JavaBean that is being validated.  The <code>ValidatorAction</code>
-     * and <code>Field</code> that are associated with a field's
-     * validation will automatically be populated if they are
-     * specified in the method signature.
+     * Note: <code>java.lang.Object</code> is reserved for the JavaBean that is being validated. The <code>ValidatorAction</code> and <code>Field</code> that
+     * are associated with a field's validation will automatically be populated if they are specified in the method signature.
      * </p>
      */
-    private String methodParams =
-            Validator.BEAN_PARAM
-            + ","
-            + Validator.VALIDATOR_ACTION_PARAM
-            + ","
-            + Validator.FIELD_PARAM;
+    private String methodParams = Validator.BEAN_PARAM + "," + Validator.VALIDATOR_ACTION_PARAM + "," + Validator.FIELD_PARAM;
 
     /**
      * The Class objects for each entry in methodParameterList.
@@ -104,9 +93,8 @@
     private Class<?>[] parameterClasses;
 
     /**
-     * The other <code>ValidatorAction</code>s that this one depends on.  If
-     * any errors occur in an action that this one depends on, this action will
-     * not be processsed.
+     * The other <code>ValidatorAction</code>s that this one depends on. If any errors occur in an action that this one depends on, this action will not be
+     * processsed.
      */
     private String depends;
 
@@ -116,419 +104,55 @@
     private String msg;
 
     /**
-     * An optional field to contain the name to be used if JavaScript is
-     * generated.
+     * An optional field to contain the name to be used if JavaScript is generated.
      */
     private String jsFunctionName;
 
     /**
-     * An optional field to contain the class path to be used to retrieve the
-     * JavaScript function.
+     * An optional field to contain the class path to be used to retrieve the JavaScript function.
      */
     private String jsFunction;
 
     /**
-     * An optional field to containing a JavaScript representation of the
-     * java method assocated with this action.
+     * An optional field to containing a JavaScript representation of the Java method assocated with this action.
      */
     private String javascript;
 
     /**
-     * If the java method matching the correct signature isn't static, the
-     * instance is stored in the action.  This assumes the method is thread
-     * safe.
+     * If the Java method matching the correct signature isn't static, the instance is stored in the action. This assumes the method is thread safe.
      */
     private Object instance;
 
     /**
-     * An internal List representation of the other <code>ValidatorAction</code>s
-     * this one depends on (if any).  This List gets updated
-     * whenever setDepends() gets called.  This is synchronized so a call to
-     * setDepends() (which clears the List) won't interfere with a call to
-     * isDependency().
+     * An internal List representation of the other <code>ValidatorAction</code>s this one depends on (if any). This List gets updated whenever setDepends()
+     * gets called. This is synchronized so a call to setDepends() (which clears the List) won't interfere with a call to isDependency().
      */
-    private final List<String> dependencyList = Collections.synchronizedList(new ArrayList<String>());
+    private final List<String> dependencyList = Collections.synchronizedList(new ArrayList<>());
 
     /**
-     * An internal List representation of all the validation method's
-     * parameters defined in the methodParams String.
+     * An internal List representation of all the validation method's parameters defined in the methodParams String.
      */
     private final List<String> methodParameterList = new ArrayList<>();
 
     /**
-     * Gets the name of the validator action.
-     * @return Validator Action name.
-     */
-    public String getName() {
-        return name;
-    }
-
-    /**
-     * Sets the name of the validator action.
-     * @param name Validator Action name.
-     */
-    public void setName(final String name) {
-        this.name = name;
-    }
-
-    /**
-     * Gets the class of the validator action.
-     * @return Class name of the validator Action.
-     */
-    public String getClassname() {
-        return classname;
-    }
-
-    /**
-     * Sets the class of the validator action.
-     * @param classname Class name of the validator Action.
-     */
-    public void setClassname(final String classname) {
-        this.classname = classname;
-    }
-
-    /**
-     * Gets the name of method being called for the validator action.
-     * @return The method name.
-     */
-    public String getMethod() {
-        return method;
-    }
-
-    /**
-     * Sets the name of method being called for the validator action.
-     * @param method The method name.
-     */
-    public void setMethod(final String method) {
-        this.method = method;
-    }
-
-    /**
-     * Gets the method parameters for the method.
-     * @return Method's parameters.
-     */
-    public String getMethodParams() {
-        return methodParams;
-    }
-
-    /**
-     * Sets the method parameters for the method.
-     * @param methodParams A comma separated list of parameters.
-     */
-    public void setMethodParams(final String methodParams) {
-        this.methodParams = methodParams;
-
-        this.methodParameterList.clear();
-
-        final StringTokenizer st = new StringTokenizer(methodParams, ",");
-        while (st.hasMoreTokens()) {
-            final String value = st.nextToken().trim();
-
-            if (value != null && !value.isEmpty()) {
-                this.methodParameterList.add(value);
-            }
-        }
-    }
-
-    /**
-     * Gets the dependencies of the validator action as a comma separated list
-     * of validator names.
-     * @return The validator action's dependencies.
-     */
-    public String getDepends() {
-        return this.depends;
-    }
-
-    /**
-     * Sets the dependencies of the validator action.
-     * @param depends A comma separated list of validator names.
-     */
-    public void setDepends(final String depends) {
-        this.depends = depends;
-
-        this.dependencyList.clear();
-
-        final StringTokenizer st = new StringTokenizer(depends, ",");
-        while (st.hasMoreTokens()) {
-            final String depend = st.nextToken().trim();
-
-            if (depend != null && !depend.isEmpty()) {
-                this.dependencyList.add(depend);
-            }
-        }
-    }
-
-    /**
-     * Gets the message associated with the validator action.
-     * @return The message for the validator action.
-     */
-    public String getMsg() {
-        return msg;
-    }
-
-    /**
-     * Sets the message associated with the validator action.
-     * @param msg The message for the validator action.
-     */
-    public void setMsg(final String msg) {
-        this.msg = msg;
-    }
-
-    /**
-     * Gets the Javascript function name.  This is optional and can
-     * be used instead of validator action name for the name of the
-     * Javascript function/object.
-     * @return The Javascript function name.
-     */
-    public String getJsFunctionName() {
-        return jsFunctionName;
-    }
-
-    /**
-     * Sets the Javascript function name.  This is optional and can
-     * be used instead of validator action name for the name of the
-     * Javascript function/object.
-     * @param jsFunctionName The Javascript function name.
-     */
-    public void setJsFunctionName(final String jsFunctionName) {
-        this.jsFunctionName = jsFunctionName;
-    }
-
-    /**
-     * Sets the fully qualified class path of the Javascript function.
-     * <p>
-     * This is optional and can be used <strong>instead</strong> of the setJavascript().
-     * Attempting to call both <code>setJsFunction</code> and <code>setJavascript</code>
-     * will result in an <code>IllegalStateException</code> being thrown. </p>
-     * <p>
-     * If <strong>neither</strong> setJsFunction or setJavascript is set then
-     * validator will attempt to load the default javascript definition.
-     * </p>
-     * <pre>
-     * <b>Examples</b>
-     *   If in the validator.xml :
-     * #1:
-     *      &lt;validator name="tire"
-     *            jsFunction="com.yourcompany.project.tireFuncion"&gt;
-     *     Validator will attempt to load com.yourcompany.project.validateTireFunction.js from
-     *     its class path.
-     * #2:
-     *    &lt;validator name="tire"&gt;
-     *      Validator will use the name attribute to try and load
-     *         org.apache.commons.validator.javascript.validateTire.js
-     *      which is the default javascript definition.
-     * </pre>
-     * @param jsFunction The Javascript function's fully qualified class path.
-     */
-    public void setJsFunction(final String jsFunction) {
-        if (javascript != null) {
-            throw new IllegalStateException("Cannot call setJsFunction() after calling setJavascript()");
-        }
-
-        this.jsFunction = jsFunction;
-    }
-
-    /**
-     * Gets the Javascript equivalent of the java class and method
-     * associated with this action.
-     * @return The Javascript validation.
-     */
-    public String getJavascript() {
-        return javascript;
-    }
-
-    /**
-     * Sets the Javascript equivalent of the java class and method
-     * associated with this action.
-     * @param javascript The Javascript validation.
-     */
-    public void setJavascript(final String javascript) {
-        if (jsFunction != null) {
-            throw new IllegalStateException("Cannot call setJavascript() after calling setJsFunction()");
-        }
-
-        this.javascript = javascript;
-    }
-
-    /**
-     * Initialize based on set.
-     */
-    protected void init() {
-        this.loadJavascriptFunction();
-    }
-
-    /**
-     * Load the javascript function specified by the given path.  For this
-     * implementation, the <code>jsFunction</code> property should contain a
-     * fully qualified package and script name, separated by periods, to be
-     * loaded from the class loader that created this instance.
+     * Dynamically runs the validation method for this validator and returns true if the data is valid.
      *
-     * TODO if the path begins with a '/' the path will be intepreted as
-     * absolute, and remain unchanged.  If this fails then it will attempt to
-     * treat the path as a file path.  It is assumed the script ends with a
-     * '.js'.
-     */
-    protected synchronized void loadJavascriptFunction() {
-
-        if (this.javascriptAlreadyLoaded()) {
-            return;
-        }
-
-        if (getLog().isTraceEnabled()) {
-            getLog().trace("  Loading function begun");
-        }
-
-        if (this.jsFunction == null) {
-            this.jsFunction = this.generateJsFunction();
-        }
-
-        final String javascriptFileName = this.formatJavascriptFileName();
-
-        if (getLog().isTraceEnabled()) {
-            getLog().trace("  Loading js function '" + javascriptFileName + "'");
-        }
-
-        this.javascript = this.readJavascriptFile(javascriptFileName);
-
-        if (getLog().isTraceEnabled()) {
-            getLog().trace("  Loading javascript function completed");
-        }
-
-    }
-
-    /**
-     * Read a javascript function from a file.
-     * @param javascriptFileName The file containing the javascript.
-     * @return The javascript function or null if it could not be loaded.
-     */
-    private String readJavascriptFile(final String javascriptFileName) {
-        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
-        if (classLoader == null) {
-            classLoader = this.getClass().getClassLoader();
-        }
-
-        InputStream is = classLoader.getResourceAsStream(javascriptFileName);
-        if (is == null) {
-            is = this.getClass().getResourceAsStream(javascriptFileName);
-        }
-
-        if (is == null) {
-            getLog().debug("  Unable to read javascript name "+javascriptFileName);
-            return null;
-        }
-
-        final StringBuilder buffer = new StringBuilder();
-        final BufferedReader reader = new BufferedReader(new InputStreamReader(is)); // TODO encoding
-        try {
-            String line = null;
-            while ((line = reader.readLine()) != null) {
-                buffer.append(line).append("\n");
-            }
-
-        } catch(final IOException e) {
-            getLog().error("Error reading javascript file.", e);
-
-        } finally {
-            try {
-                reader.close();
-            } catch(final IOException e) {
-                getLog().error("Error closing stream to javascript file.", e);
-            }
-        }
-
-        final String function = buffer.toString();
-        return function.equals("") ? null : function;
-    }
-
-    /**
-     * @return A filename suitable for passing to a
-     * ClassLoader.getResourceAsStream() method.
-     */
-    private String formatJavascriptFileName() {
-        String fname = this.jsFunction.substring(1);
-
-        if (!this.jsFunction.startsWith("/")) {
-            fname = jsFunction.replace('.', '/') + ".js";
-        }
-
-        return fname;
-    }
-
-    /**
-     * @return true if the javascript for this action has already been loaded.
-     */
-    private boolean javascriptAlreadyLoaded() {
-        return (this.javascript != null);
-    }
-
-    /**
-     * Used to generate the javascript name when it is not specified.
-     */
-    private String generateJsFunction() {
-        final StringBuilder jsName =
-                new StringBuilder("org.apache.commons.validator.javascript");
-
-        jsName.append(".validate");
-        jsName.append(name.substring(0, 1).toUpperCase());
-        jsName.append(name.substring(1));
-
-        return jsName.toString();
-    }
-
-    /**
-     * Checks whether or not the value passed in is in the depends field.
-     * @param validatorName Name of the dependency to check.
-     * @return Whether the named validator is a dependant.
-     */
-    public boolean isDependency(final String validatorName) {
-        return this.dependencyList.contains(validatorName);
-    }
-
-    /**
-     * Returns the dependent validator names as an unmodifiable
-     * <code>List</code>.
-     * @return List of the validator action's depedents.
-     */
-    public List<String> getDependencyList() {
-        return Collections.unmodifiableList(this.dependencyList);
-    }
-
-    /**
-     * Returns a string representation of the object.
-     * @return a string representation.
-     */
-    @Override
-    public String toString() {
-        final StringBuilder results = new StringBuilder("ValidatorAction: ");
-        results.append(name);
-        results.append("\n");
-
-        return results.toString();
-    }
-
-    /**
-     * Dynamically runs the validation method for this validator and returns
-     * true if the data is valid.
      * @param field
-     * @param params A Map of class names to parameter values.
+     * @param params  A Map of class names to parameter values.
      * @param results
-     * @param pos The index of the list property to validate if it's indexed.
+     * @param pos     The index of the list property to validate if it's indexed.
      * @throws ValidatorException
      */
-    boolean executeValidationMethod(
-        final Field field,
-        // TODO What is this the correct value type?
-        // both ValidatorAction and Validator are added as parameters
-        final Map<String, Object> params,
-        final ValidatorResults results,
-        final int pos)
-        throws ValidatorException {
+    boolean executeValidationMethod(final Field field,
+            // TODO What is this the correct value type?
+            // both ValidatorAction and Validator are added as parameters
+            final Map<String, Object> params, final ValidatorResults results, final int pos) throws ValidatorException {
 
         params.put(Validator.VALIDATOR_ACTION_PARAM, this);
 
         try {
             if (this.validationMethod == null) {
-                synchronized(this) {
+                synchronized (this) {
                     final ClassLoader loader = this.getClassLoader(params);
                     this.loadValidationClass(loader);
                     this.loadParameterClasses(loader);
@@ -544,10 +168,7 @@
 
             Object result = null;
             try {
-                result =
-                    validationMethod.invoke(
-                        getValidationClassInstance(),
-                        paramValues);
+                result = validationMethod.invoke(getValidationClassInstance(), paramValues);
 
             } catch (IllegalArgumentException | IllegalAccessException e) {
                 throw new ValidatorException(e.getMessage());
@@ -563,7 +184,7 @@
             }
 
             final boolean valid = this.isValid(result);
-            if (!valid || (valid && !onlyReturnErrors(params))) {
+            if (!valid || valid && !onlyReturnErrors(params)) {
                 results.add(field, this.name, valid, result);
             }
 
@@ -571,16 +192,14 @@
                 return false;
             }
 
-            // TODO This catch block remains for backward compatibility.  Remove
+            // TODO This catch block remains for backward compatibility. Remove
             // this for Validator 2.0 when exception scheme changes.
         } catch (final Exception e) {
             if (e instanceof ValidatorException) {
                 throw (ValidatorException) e;
             }
 
-            getLog().error(
-                "Unhandled exception thrown during validation: " + e.getMessage(),
-                e);
+            getLog().error("Unhandled exception thrown during validation: " + e.getMessage(), e);
 
             results.add(field, this.name, false);
             return false;
@@ -590,52 +209,280 @@
     }
 
     /**
-     * Load the Method object for the configured validation method name.
-     * @throws ValidatorException
+     * @return A file name suitable for passing to a {@link ClassLoader#getResourceAsStream(String)} method.
      */
-    private void loadValidationMethod() throws ValidatorException {
-        if (this.validationMethod != null) {
-            return;
+    private String formatJavaScriptFileName() {
+        String fname = this.jsFunction.substring(1);
+
+        if (!this.jsFunction.startsWith("/")) {
+            fname = jsFunction.replace('.', '/') + ".js";
         }
 
-        try {
-            this.validationMethod =
-                this.validationClass.getMethod(this.method, this.parameterClasses);
-
-        } catch (final NoSuchMethodException e) {
-            throw new ValidatorException("No such validation method: " +
-                e.getMessage());
-        }
+        return fname;
     }
 
     /**
-     * Load the Class object for the configured validation class name.
-     * @param loader The ClassLoader used to load the Class object.
-     * @throws ValidatorException
+     * Used to generate the JavaScript name when it is not specified.
      */
-    private void loadValidationClass(final ClassLoader loader)
-        throws ValidatorException {
+    private String generateJsFunction() {
+        final StringBuilder jsName = new StringBuilder("org.apache.commons.validator.javascript");
 
-        if (this.validationClass != null) {
-            return;
-        }
+        jsName.append(".validate");
+        jsName.append(name.substring(0, 1).toUpperCase());
+        jsName.append(name.substring(1));
 
-        try {
-            this.validationClass = loader.loadClass(this.classname);
-        } catch (final ClassNotFoundException e) {
-            throw new ValidatorException(e.toString());
-        }
+        return jsName.toString();
     }
 
     /**
-     * Converts a List of parameter class names into their Class objects.
-     * Stores the output in {@link #parameterClasses}.  This
-     * array is in the same order as the given List and is suitable for passing
-     * to the validation method.
+     * Returns the ClassLoader set in the Validator contained in the parameter Map.
+     */
+    private ClassLoader getClassLoader(final Map<String, Object> params) {
+        final Validator v = getValidator(params);
+        return v.getClassLoader();
+    }
+
+    /**
+     * Gets the class of the validator action.
+     *
+     * @return Class name of the validator Action.
+     */
+    public String getClassname() {
+        return className;
+    }
+
+    /**
+     * Returns the dependent validator names as an unmodifiable <code>List</code>.
+     *
+     * @return List of the validator action's depedents.
+     */
+    public List<String> getDependencyList() {
+        return Collections.unmodifiableList(this.dependencyList);
+    }
+
+    /**
+     * Gets the dependencies of the validator action as a comma separated list of validator names.
+     *
+     * @return The validator action's dependencies.
+     */
+    public String getDepends() {
+        return this.depends;
+    }
+
+    /**
+     * Gets the JavaScript equivalent of the Java class and method associated with this action.
+     *
+     * @return The JavaScript validation.
+     */
+    public synchronized String getJavascript() {
+        return javascript;
+    }
+
+    /**
+     * Gets the JavaScript function name. This is optional and can be used instead of validator action name for the name of the JavaScript function/object.
+     *
+     * @return The JavaScript function name.
+     */
+    public String getJsFunctionName() {
+        return jsFunctionName;
+    }
+
+    /**
+     * Accessor method for Log instance.
+     *
+     * The Log instance variable is transient and accessing it through this method ensures it is re-initialized when this instance is de-serialized.
+     *
+     * @return The Log instance.
+     */
+    private Log getLog() {
+        if (log == null) {
+            log = LogFactory.getLog(ValidatorAction.class);
+        }
+        return log;
+    }
+
+    /**
+     * Gets the name of method being called for the validator action.
+     *
+     * @return The method name.
+     */
+    public String getMethod() {
+        return method;
+    }
+
+    /**
+     * Gets the method parameters for the method.
+     *
+     * @return Method's parameters.
+     */
+    public String getMethodParams() {
+        return methodParams;
+    }
+
+    /**
+     * Gets the message associated with the validator action.
+     *
+     * @return The message for the validator action.
+     */
+    public String getMsg() {
+        return msg;
+    }
+
+    /**
+     * Gets the name of the validator action.
+     *
+     * @return Validator Action name.
+     */
+    public String getName() {
+        return name;
+    }
+
+    /**
+     * Converts a List of parameter class names into their values contained in the parameters Map.
+     *
+     * @param params A Map of class names to parameter values.
+     * @return An array containing the value object for each parameter. This array is in the same order as the given List and is suitable for passing to the
+     *         validation method.
+     */
+    private Object[] getParameterValues(final Map<String, ? super Object> params) {
+
+        final Object[] paramValue = new Object[this.methodParameterList.size()];
+
+        for (int i = 0; i < this.methodParameterList.size(); i++) {
+            final String paramClassName = this.methodParameterList.get(i);
+            paramValue[i] = params.get(paramClassName);
+        }
+
+        return paramValue;
+    }
+
+    /**
+     * Gets an instance of the validation class or null if the validation method is static so does not require an instance to be executed.
+     */
+    private Object getValidationClassInstance() throws ValidatorException {
+        if (Modifier.isStatic(this.validationMethod.getModifiers())) {
+            this.instance = null;
+
+        } else if (this.instance == null) {
+            try {
+                this.instance = this.validationClass.getConstructor().newInstance();
+            } catch (final ReflectiveOperationException e) {
+                final String msg1 = "Couldn't create instance of " + this.className + ".  " + e.getMessage();
+
+                throw new ValidatorException(msg1);
+            }
+        }
+
+        return this.instance;
+    }
+
+    private Validator getValidator(final Map<String, Object> params) {
+        return (Validator) params.get(Validator.VALIDATOR_PARAM);
+    }
+
+    /**
+     * Modifies the paramValue array with indexed fields.
+     *
+     * @param field
+     * @param pos
+     * @param paramValues
+     */
+    private void handleIndexedField(final Field field, final int pos, final Object[] paramValues) throws ValidatorException {
+
+        final int beanIndex = this.methodParameterList.indexOf(Validator.BEAN_PARAM);
+        final int fieldIndex = this.methodParameterList.indexOf(Validator.FIELD_PARAM);
+
+        final Object[] indexedList = field.getIndexedProperty(paramValues[beanIndex]);
+
+        // Set current iteration object to the parameter array
+        paramValues[beanIndex] = indexedList[pos];
+
+        // Set field clone with the key modified to represent
+        // the current field
+        final Field indexedField = (Field) field.clone();
+        indexedField.setKey(ValidatorUtils.replace(indexedField.getKey(), Field.TOKEN_INDEXED, "[" + pos + "]"));
+
+        paramValues[fieldIndex] = indexedField;
+    }
+
+    /**
+     * Initialize based on set.
+     */
+    protected void init() {
+        this.loadJavascriptFunction();
+    }
+
+    /**
+     * Checks whether or not the value passed in is in the depends field.
+     *
+     * @param validatorName Name of the dependency to check.
+     * @return Whether the named validator is a dependant.
+     */
+    public boolean isDependency(final String validatorName) {
+        return this.dependencyList.contains(validatorName);
+    }
+
+    /**
+     * If the result object is a <code>Boolean</code>, it will return its value. If not it will return {@code false} if the object is {@code null} and
+     * {@code true} if it isn't.
+     */
+    private boolean isValid(final Object result) {
+        if (result instanceof Boolean) {
+            final Boolean valid = (Boolean) result;
+            return valid.booleanValue();
+        }
+        return result != null;
+    }
+
+    /**
+     * @return true if the JavaScript for this action has already been loaded.
+     */
+    private boolean javaScriptAlreadyLoaded() {
+        return this.javascript != null;
+    }
+
+    /**
+     * Load the JavaScript function specified by the given path. For this implementation, the <code>jsFunction</code> property should contain a fully qualified
+     * package and script name, separated by periods, to be loaded from the class loader that created this instance.
+     *
+     * TODO if the path begins with a '/' the path will be intepreted as absolute, and remain unchanged. If this fails then it will attempt to treat the path as
+     * a file path. It is assumed the script ends with a '.js'.
+     */
+    protected synchronized void loadJavascriptFunction() {
+
+        if (this.javaScriptAlreadyLoaded()) {
+            return;
+        }
+
+        if (getLog().isTraceEnabled()) {
+            getLog().trace("  Loading function begun");
+        }
+
+        if (this.jsFunction == null) {
+            this.jsFunction = this.generateJsFunction();
+        }
+
+        final String javaScriptFileName = this.formatJavaScriptFileName();
+
+        if (getLog().isTraceEnabled()) {
+            getLog().trace("  Loading js function '" + javaScriptFileName + "'");
+        }
+
+        this.javascript = this.readJavaScriptFile(javaScriptFileName);
+
+        if (getLog().isTraceEnabled()) {
+            getLog().trace("  Loading JavaScript function completed");
+        }
+
+    }
+
+    /**
+     * Converts a List of parameter class names into their Class objects. Stores the output in {@link #parameterClasses}. This array is in the same order as the
+     * given List and is suitable for passing to the validation method.
+     *
      * @throws ValidatorException if a class cannot be loaded.
      */
-    private void loadParameterClasses(final ClassLoader loader)
-        throws ValidatorException {
+    private void loadParameterClasses(final ClassLoader loader) throws ValidatorException {
 
         if (this.parameterClasses != null) {
             return;
@@ -658,125 +505,257 @@
     }
 
     /**
-     * Converts a List of parameter class names into their values contained in
-     * the parameters Map.
-     * @param params A Map of class names to parameter values.
-     * @return An array containing the value object for each parameter.  This
-     * array is in the same order as the given List and is suitable for passing
-     * to the validation method.
-     */
-    private Object[] getParameterValues(final Map<String, ? super Object> params) {
-
-        final Object[] paramValue = new Object[this.methodParameterList.size()];
-
-        for (int i = 0; i < this.methodParameterList.size(); i++) {
-            final String paramClassName = this.methodParameterList.get(i);
-            paramValue[i] = params.get(paramClassName);
-        }
-
-        return paramValue;
-    }
-
-    /**
-     * Return an instance of the validation class or null if the validation
-     * method is static so does not require an instance to be executed.
-     */
-    private Object getValidationClassInstance() throws ValidatorException {
-        if (Modifier.isStatic(this.validationMethod.getModifiers())) {
-            this.instance = null;
-
-        } else if (this.instance == null) {
-            try {
-                this.instance = this.validationClass.newInstance();
-            } catch (InstantiationException | IllegalAccessException e) {
-                final String msg1 =
-                    "Couldn't create instance of "
-                        + this.classname
-                        + ".  "
-                        + e.getMessage();
-
-                throw new ValidatorException(msg1);
-            }
-        }
-
-        return this.instance;
-    }
-
-    /**
-     * Modifies the paramValue array with indexed fields.
+     * Load the Class object for the configured validation class name.
      *
-     * @param field
-     * @param pos
-     * @param paramValues
+     * @param loader The ClassLoader used to load the Class object.
+     * @throws ValidatorException
      */
-    private void handleIndexedField(final Field field, final int pos, final Object[] paramValues)
-        throws ValidatorException {
+    private void loadValidationClass(final ClassLoader loader) throws ValidatorException {
 
-        final int beanIndex = this.methodParameterList.indexOf(Validator.BEAN_PARAM);
-        final int fieldIndex = this.methodParameterList.indexOf(Validator.FIELD_PARAM);
-
-        final Object indexedList[] = field.getIndexedProperty(paramValues[beanIndex]);
-
-        // Set current iteration object to the parameter array
-        paramValues[beanIndex] = indexedList[pos];
-
-        // Set field clone with the key modified to represent
-        // the current field
-        final Field indexedField = (Field) field.clone();
-        indexedField.setKey(
-            ValidatorUtils.replace(
-                indexedField.getKey(),
-                Field.TOKEN_INDEXED,
-                "[" + pos + "]"));
-
-        paramValues[fieldIndex] = indexedField;
-    }
-
-    /**
-     * If the result object is a <code>Boolean</code>, it will return its
-     * value.  If not it will return <code>false</code> if the object is
-     * <code>null</code> and <code>true</code> if it isn't.
-     */
-    private boolean isValid(final Object result) {
-        if (result instanceof Boolean) {
-            final Boolean valid = (Boolean) result;
-            return valid.booleanValue();
+        if (this.validationClass != null) {
+            return;
         }
-        return result != null;
+
+        try {
+            this.validationClass = loader.loadClass(this.className);
+        } catch (final ClassNotFoundException e) {
+            throw new ValidatorException(e.toString());
+        }
     }
 
     /**
-     * Returns the ClassLoader set in the Validator contained in the parameter
-     * Map.
+     * Load the Method object for the configured validation method name.
+     *
+     * @throws ValidatorException
      */
-    private ClassLoader getClassLoader(final Map<String, Object> params) {
-        final Validator v = (Validator) params.get(Validator.VALIDATOR_PARAM);
-        return v.getClassLoader();
+    private void loadValidationMethod() throws ValidatorException {
+        if (this.validationMethod != null) {
+            return;
+        }
+
+        try {
+            this.validationMethod = this.validationClass.getMethod(this.method, this.parameterClasses);
+
+        } catch (final NoSuchMethodException e) {
+            throw new ValidatorException("No such validation method: " + e.getMessage());
+        }
     }
 
     /**
-     * Returns the onlyReturnErrors setting in the Validator contained in the
-     * parameter Map.
+     * Returns the onlyReturnErrors setting in the Validator contained in the parameter Map.
      */
     private boolean onlyReturnErrors(final Map<String, Object> params) {
-        final Validator v = (Validator) params.get(Validator.VALIDATOR_PARAM);
+        final Validator v = getValidator(params);
         return v.getOnlyReturnErrors();
     }
 
     /**
-     * Accessor method for Log instance.
+     * Opens an input stream for reading the specified resource.
+     * <p>
+     * The search order is described in the documentation for {@link ClassLoader#getResource(String)}.
+     * </p>
      *
-     * The Log instance variable is transient and
-     * accessing it through this method ensures it
-     * is re-initialized when this instance is
-     * de-serialized.
-     *
-     * @return The Log instance.
+     * @param name The resource name
+     * @return An input stream for reading the resource, or {@code null} if the resource could not be found
      */
-    private Log getLog() {
-        if (log == null) {
-            log =  LogFactory.getLog(ValidatorAction.class);
+    private InputStream openInputStream(final String javaScriptFileName, final ClassLoader classLoader) {
+        InputStream is = null;
+        if (classLoader != null) {
+            is = classLoader.getResourceAsStream(javaScriptFileName);
         }
-        return log;
+        if (is == null) {
+            return getClass().getResourceAsStream(javaScriptFileName);
+        }
+        return is;
+    }
+
+    /**
+     * Reads a JavaScript function from a file.
+     *
+     * @param javaScriptFileName The file containing the JavaScript.
+     * @return The JavaScript function or null if it could not be loaded.
+     */
+    private String readJavaScriptFile(final String javaScriptFileName) {
+        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+        if (classLoader == null) {
+            classLoader = getClass().getClassLoader();
+        }
+        // BufferedReader closes InputStreamReader closes InputStream
+        final InputStream is = openInputStream(javaScriptFileName, classLoader);
+        if (is == null) {
+            getLog().debug("  Unable to read javascript name " + javaScriptFileName);
+            return null;
+        }
+        final StringBuilder buffer = new StringBuilder();
+        // TODO encoding
+        try (BufferedReader reader = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+                buffer.append(line).append("\n");
+            }
+        } catch (final IOException e) {
+            getLog().error("Error reading JavaScript file.", e);
+
+        }
+        final String function = buffer.toString();
+        return function.isEmpty() ? null : function;
+    }
+
+    /**
+     * Sets the class of the validator action.
+     *
+     * @param className Class name of the validator Action.
+     * @deprecated Use {@link #setClassName(String)}.
+     */
+    @Deprecated
+    public void setClassname(final String className) {
+        this.className = className;
+    }
+
+    /**
+     * Sets the class of the validator action.
+     *
+     * @param className Class name of the validator Action.
+     */
+    public void setClassName(final String className) {
+        this.className = className;
+    }
+
+    /**
+     * Sets the dependencies of the validator action.
+     *
+     * @param depends A comma separated list of validator names.
+     */
+    public void setDepends(final String depends) {
+        this.depends = depends;
+
+        this.dependencyList.clear();
+
+        final StringTokenizer st = new StringTokenizer(depends, ",");
+        while (st.hasMoreTokens()) {
+            final String depend = st.nextToken().trim();
+
+            if (depend != null && !depend.isEmpty()) {
+                this.dependencyList.add(depend);
+            }
+        }
+    }
+
+    /**
+     * Sets the JavaScript equivalent of the Java class and method associated with this action.
+     *
+     * @param javaScript The JavaScript validation.
+     */
+    public synchronized void setJavascript(final String javaScript) {
+        if (jsFunction != null) {
+            throw new IllegalStateException("Cannot call setJavascript() after calling setJsFunction()");
+        }
+
+        this.javascript = javaScript;
+    }
+
+    /**
+     * Sets the fully qualified class path of the JavaScript function.
+     * <p>
+     * This is optional and can be used <strong>instead</strong> of the setJavascript(). Attempting to call both <code>setJsFunction</code> and
+     * <code>setJavascript</code> will result in an <code>IllegalStateException</code> being thrown.
+     * </p>
+     * <p>
+     * If <strong>neither</strong> setJsFunction or setJavascript is set then validator will attempt to load the default JavaScript definition.
+     * </p>
+     *
+     * <pre>
+     * <b>Examples</b>
+     *   If in the validator.xml :
+     * #1:
+     *      &lt;validator name="tire"
+     *            jsFunction="com.yourcompany.project.tireFuncion"&gt;
+     *     Validator will attempt to load com.yourcompany.project.validateTireFunction.js from
+     *     its class path.
+     * #2:
+     *    &lt;validator name="tire"&gt;
+     *      Validator will use the name attribute to try and load
+     *         org.apache.commons.validator.javascript.validateTire.js
+     *      which is the default JavaScript definition.
+     * </pre>
+     *
+     * @param jsFunction The JavaScript function's fully qualified class path.
+     */
+    public synchronized void setJsFunction(final String jsFunction) {
+        if (javascript != null) {
+            throw new IllegalStateException("Cannot call setJsFunction() after calling setJavascript()");
+        }
+
+        this.jsFunction = jsFunction;
+    }
+
+    /**
+     * Sets the JavaScript function name. This is optional and can be used instead of validator action name for the name of the JavaScript function/object.
+     *
+     * @param jsFunctionName The JavaScript function name.
+     */
+    public void setJsFunctionName(final String jsFunctionName) {
+        this.jsFunctionName = jsFunctionName;
+    }
+
+    /**
+     * Sets the name of method being called for the validator action.
+     *
+     * @param method The method name.
+     */
+    public void setMethod(final String method) {
+        this.method = method;
+    }
+
+    /**
+     * Sets the method parameters for the method.
+     *
+     * @param methodParams A comma separated list of parameters.
+     */
+    public void setMethodParams(final String methodParams) {
+        this.methodParams = methodParams;
+
+        this.methodParameterList.clear();
+
+        final StringTokenizer st = new StringTokenizer(methodParams, ",");
+        while (st.hasMoreTokens()) {
+            final String value = st.nextToken().trim();
+
+            if (value != null && !value.isEmpty()) {
+                this.methodParameterList.add(value);
+            }
+        }
+    }
+
+    /**
+     * Sets the message associated with the validator action.
+     *
+     * @param msg The message for the validator action.
+     */
+    public void setMsg(final String msg) {
+        this.msg = msg;
+    }
+
+    /**
+     * Sets the name of the validator action.
+     *
+     * @param name Validator Action name.
+     */
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Returns a string representation of the object.
+     *
+     * @return a string representation.
+     */
+    @Override
+    public String toString() {
+        final StringBuilder results = new StringBuilder("ValidatorAction: ");
+        results.append(name);
+        results.append("\n");
+
+        return results.toString();
     }
 }
diff --git a/src/main/java/org/apache/commons/validator/ValidatorResources.java b/src/main/java/org/apache/commons/validator/ValidatorResources.java
index d18f258..1af9944 100644
--- a/src/main/java/org/apache/commons/validator/ValidatorResources.java
+++ b/src/main/java/org/apache/commons/validator/ValidatorResources.java
@@ -62,7 +62,7 @@
      * the versions of the configuration file DTDs that we know about.  There
      * <strong>MUST</strong> be an even number of Strings in this list!
      */
-    private static final String REGISTRATIONS[] = {
+    private static final String[] REGISTRATIONS = {
         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN",
         "/org/apache/commons/validator/resources/validator_1_0.dtd",
         "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0.1//EN",
@@ -79,6 +79,14 @@
         "/org/apache/commons/validator/resources/validator_1_4_0.dtd"
     };
 
+    /**
+     * The default locale on our server.
+     */
+    protected static Locale defaultLocale = Locale.getDefault();
+
+    private static final String ARGS_PATTERN
+               = "form-validation/formset/form/field/arg";
+
     private transient Log log = LogFactory.getLog(ValidatorResources.class);
 
     /**
@@ -106,9 +114,10 @@
     protected FastHashMap hActions = new FastHashMap(); // <String, ValidatorAction>
 
     /**
-     * The default locale on our server.
+     * This is the default <code>FormSet</code> (without locale). (We probably don't need
+     * the defaultLocale anymore.)
      */
-    protected static Locale defaultLocale = Locale.getDefault();
+    protected FormSet defaultFormSet;
 
     /**
      * Create an empty ValidatorResources object.
@@ -117,12 +126,6 @@
     }
 
     /**
-     * This is the default <code>FormSet</code> (without locale). (We probably don't need
-     * the defaultLocale anymore.)
-     */
-    protected FormSet defaultFormSet;
-
-    /**
      * Create a ValidatorResources object from an InputStream.
      *
      * @param in InputStream to a validation.xml configuration file.  It's the client's
@@ -235,111 +238,6 @@
     }
 
     /**
-     *  Initialize the digester.
-     */
-    private Digester initDigester() {
-        URL rulesUrl = this.getClass().getResource(VALIDATOR_RULES);
-        if (rulesUrl == null) {
-            // Fix for Issue# VALIDATOR-195
-            rulesUrl = ValidatorResources.class.getResource(VALIDATOR_RULES);
-        }
-        if (getLog().isDebugEnabled()) {
-            getLog().debug("Loading rules from '" + rulesUrl + "'");
-        }
-        final Digester digester = DigesterLoader.createDigester(rulesUrl);
-        digester.setNamespaceAware(true);
-        digester.setValidating(true);
-        digester.setUseContextClassLoader(true);
-
-        // Add rules for arg0-arg3 elements
-        addOldArgRules(digester);
-
-        // register DTDs
-        for (int i = 0; i < REGISTRATIONS.length; i += 2) {
-            final URL url = this.getClass().getResource(REGISTRATIONS[i + 1]);
-            if (url != null) {
-                digester.register(REGISTRATIONS[i], url.toString());
-            }
-        }
-        return digester;
-    }
-
-    private static final String ARGS_PATTERN
-               = "form-validation/formset/form/field/arg";
-
-    /**
-     * Create a <code>Rule</code> to handle <code>arg0-arg3</code>
-     * elements. This will allow validation.xml files that use the
-     * versions of the DTD prior to Validator 1.2.0 to continue
-     * working.
-     */
-    private void addOldArgRules(final Digester digester) {
-
-        // Create a new rule to process args elements
-        final Rule rule = new Rule() {
-            @Override
-            public void begin(final String namespace, final String name,
-                               final Attributes attributes) throws Exception {
-                // Create the Arg
-                final Arg arg = new Arg();
-                arg.setKey(attributes.getValue("key"));
-                arg.setName(attributes.getValue("name"));
-                if ("false".equalsIgnoreCase(attributes.getValue("resource"))) {
-                    arg.setResource(false);
-                }
-                try {
-                    final int length = "arg".length(); // skip the arg prefix
-                    arg.setPosition(Integer.parseInt(name.substring(length)));
-                } catch (final Exception ex) {
-                    getLog().error("Error parsing Arg position: "
-                               + name + " " + arg + " " + ex);
-                }
-
-                // Add the arg to the parent field
-                ((Field)getDigester().peek(0)).addArg(arg);
-            }
-        };
-
-        // Add the rule for each of the arg elements
-        digester.addRule(ARGS_PATTERN + "0", rule);
-        digester.addRule(ARGS_PATTERN + "1", rule);
-        digester.addRule(ARGS_PATTERN + "2", rule);
-        digester.addRule(ARGS_PATTERN + "3", rule);
-
-    }
-
-    /**
-     * Add a <code>FormSet</code> to this <code>ValidatorResources</code>
-     * object.  It will be associated with the <code>Locale</code> of the
-     * <code>FormSet</code>.
-     * @param fs The form set to add.
-     * @since 1.1
-     */
-    public void addFormSet(final FormSet fs) {
-        final String key = this.buildKey(fs);
-        if (key.isEmpty()) {// there can only be one default formset
-            if (getLog().isWarnEnabled() && defaultFormSet != null) {
-                // warn the user he might not get the expected results
-                getLog().warn("Overriding default FormSet definition.");
-            }
-            defaultFormSet = fs;
-        } else {
-            final FormSet formset = getFormSets().get(key);
-            if (formset == null) {// it hasn't been included yet
-                if (getLog().isDebugEnabled()) {
-                    getLog().debug("Adding FormSet '" + fs + "'.");
-                }
-            } else if (getLog().isWarnEnabled()) {// warn the user he might not
-                                                // get the expected results
-                getLog()
-                        .warn("Overriding FormSet definition. Duplicate for locale: "
-                                + key);
-            }
-            getFormSets().put(key, fs);
-        }
-    }
-
-    /**
      * Add a global constant to the resource.
      * @param name The constant name.
      * @param value The constant value.
@@ -353,9 +251,76 @@
     }
 
     /**
+     * Add a <code>FormSet</code> to this <code>ValidatorResources</code>
+     * object.  It will be associated with the <code>Locale</code> of the
+     * <code>FormSet</code>.
+     * @param fs The form set to add.
+     * @since 1.1
+     */
+    public void addFormSet(final FormSet fs) {
+        final String key = this.buildKey(fs);
+        if (key.isEmpty()) { // there can only be one default formset
+            if (getLog().isWarnEnabled() && defaultFormSet != null) {
+                // warn the user he might not get the expected results
+                getLog().warn("Overriding default FormSet definition.");
+            }
+            defaultFormSet = fs;
+        } else {
+            final FormSet formset = getFormSets().get(key);
+            if (formset == null) { // it hasn't been included yet
+                if (getLog().isDebugEnabled()) {
+                    getLog().debug("Adding FormSet '" + fs + "'.");
+                }
+            } else if (getLog().isWarnEnabled()) { // warn the user he might not
+                                                   // get the expected results
+                getLog().warn("Overriding FormSet definition. Duplicate for locale: " + key);
+            }
+            getFormSets().put(key, fs);
+        }
+    }
+
+    /**
+     * Create a <code>Rule</code> to handle <code>arg0-arg3</code>
+     * elements. This will allow validation.xml files that use the
+     * versions of the DTD prior to Validator 1.2.0 to continue
+     * working.
+     */
+    private void addOldArgRules(final Digester digester) {
+        // Create a new rule to process args elements
+        final Rule rule = new Rule() {
+            @Override
+            public void begin(final String namespace, final String name, final Attributes attributes) {
+                // Create the Arg
+                final Arg arg = new Arg();
+                arg.setKey(attributes.getValue("key"));
+                arg.setName(attributes.getValue("name"));
+                if ("false".equalsIgnoreCase(attributes.getValue("resource"))) {
+                    arg.setResource(false);
+                }
+                try {
+                    final int length = "arg".length(); // skip the arg prefix
+                    arg.setPosition(Integer.parseInt(name.substring(length)));
+                } catch (final Exception ex) {
+                    getLog().error("Error parsing Arg position: " + name + " " + arg + " " + ex);
+                }
+
+                // Add the arg to the parent field
+                ((Field) getDigester().peek(0)).addArg(arg);
+            }
+        };
+
+        // Add the rule for each of the arg elements
+        digester.addRule(ARGS_PATTERN + "0", rule);
+        digester.addRule(ARGS_PATTERN + "1", rule);
+        digester.addRule(ARGS_PATTERN + "2", rule);
+        digester.addRule(ARGS_PATTERN + "3", rule);
+
+    }
+
+    /**
      * Add a <code>ValidatorAction</code> to the resource.  It also creates an
      * instance of the class based on the <code>ValidatorAction</code>s
-     * classname and retrieves the <code>Method</code> instance and sets them
+     * class name and retrieves the <code>Method</code> instance and sets them
      * in the <code>ValidatorAction</code>.
      * @param va The validator action.
      */
@@ -370,23 +335,6 @@
     }
 
     /**
-     * Get a <code>ValidatorAction</code> based on it's name.
-     * @param key The validator action key.
-     * @return The validator action.
-     */
-    public ValidatorAction getValidatorAction(final String key) {
-        return getActions().get(key);
-    }
-
-    /**
-     * Get an unmodifiable <code>Map</code> of the <code>ValidatorAction</code>s.
-     * @return Map of validator actions.
-     */
-    public Map<String, ValidatorAction> getValidatorActions() {
-        return Collections.unmodifiableMap(getActions());
-    }
-
-    /**
      * Builds a key to store the <code>FormSet</code> under based on it's
      * language, country, and variant values.
      * @param fs The Form Set.
@@ -401,10 +349,30 @@
      * Assembles a Locale code from the given parts.
      */
     private String buildLocale(final String lang, final String country, final String variant) {
-        String key = ((lang != null && !lang.isEmpty()) ? lang : "");
-        key += ((country != null && !country.isEmpty()) ? "_" + country : "");
-        key += ((variant != null && !variant.isEmpty()) ? "_" + variant : "");
-        return key;
+        final StringBuilder key = new StringBuilder().append(lang != null && !lang.isEmpty() ? lang : "");
+        key.append(country != null && !country.isEmpty() ? "_" + country : "");
+        key.append(variant != null && !variant.isEmpty() ? "_" + variant : "");
+        return key.toString();
+    }
+
+    /**
+     * Returns a Map of String ValidatorAction names to their ValidatorAction.
+     * @return Map of Validator Actions
+     * @since 1.2.0
+     */
+    @SuppressWarnings("unchecked") // FastHashMap is not generic
+    protected Map<String, ValidatorAction> getActions() {
+        return hActions;
+    }
+
+    /**
+     * Returns a Map of String constant names to their String values.
+     * @return Map of Constants
+     * @since 1.2.0
+     */
+    @SuppressWarnings("unchecked") // FastHashMap is not generic
+    protected Map<String, String> getConstants() {
+        return hConstants;
     }
 
     /**
@@ -444,8 +412,7 @@
      * @return The validator Form.
      * @since 1.1
      */
-    public Form getForm(final String language, final String country, final String variant,
-            final String formKey) {
+    public Form getForm(final String language, final String country, final String variant, final String formKey) {
 
         Form form = null;
 
@@ -457,8 +424,7 @@
                 form = formSet.getForm(formKey);
             }
         }
-        final String localeKey  = key;
-
+        final String localeKey = key;
 
         // Try language/country
         if (form == null) {
@@ -490,12 +456,10 @@
 
         if (form == null) {
             if (getLog().isWarnEnabled()) {
-                getLog().warn("Form '" + formKey + "' not found for locale '" +
-                         localeKey + "'");
+                getLog().warn("Form '" + formKey + "' not found for locale '" + localeKey + "'");
             }
         } else if (getLog().isDebugEnabled()) {
-            getLog().debug("Form '" + formKey + "' found in formset '" +
-                      key + "' for locale '" + localeKey + "'");
+            getLog().debug("Form '" + formKey + "' found in formset '" + key + "' for locale '" + localeKey + "'");
         }
 
         return form;
@@ -503,6 +467,129 @@
     }
 
     /**
+     * <p>Gets a <code>FormSet</code> based on the language, country
+     *    and variant.</p>
+     * @param language The locale's language.
+     * @param country The locale's country.
+     * @param variant The locale's language variant.
+     * @return The FormSet for a locale.
+     * @since 1.2
+     */
+    FormSet getFormSet(final String language, final String country, final String variant) {
+        final String key = buildLocale(language, country, variant);
+        if (key.isEmpty()) {
+            return defaultFormSet;
+        }
+        return getFormSets().get(key);
+    }
+
+    /**
+     * Returns a Map of String locale keys to Lists of their FormSets.
+     * @return Map of Form sets
+     * @since 1.2.0
+     */
+    @SuppressWarnings("unchecked") // FastHashMap is not generic
+    protected Map<String, FormSet> getFormSets() {
+        return hFormSets;
+    }
+
+    /**
+     * Accessor method for Log instance.
+     *
+     * The Log instance variable is transient and
+     * accessing it through this method ensures it
+     * is re-initialized when this instance is
+     * de-serialized.
+     *
+     * @return The Log instance.
+     */
+    private Log getLog() {
+        if (log == null) {
+            log = LogFactory.getLog(ValidatorResources.class);
+        }
+        return log;
+    }
+
+    /**
+     * Finds the given formSet's parent. ex: A formSet with locale en_UK_TEST1
+     * has a direct parent in the formSet with locale en_UK. If it doesn't
+     * exist, find the formSet with locale en, if no found get the
+     * defaultFormSet.
+     *
+     * @param fs
+     *            the formSet we want to get the parent from
+     * @return fs's parent
+     */
+    private FormSet getParent(final FormSet fs) {
+
+        FormSet parent = null;
+        if (fs.getType() == FormSet.LANGUAGE_FORMSET) {
+            parent = defaultFormSet;
+        } else if (fs.getType() == FormSet.COUNTRY_FORMSET) {
+            parent = getFormSets().get(buildLocale(fs.getLanguage(), null, null));
+            if (parent == null) {
+                parent = defaultFormSet;
+            }
+        } else if (fs.getType() == FormSet.VARIANT_FORMSET) {
+            parent = getFormSets().get(buildLocale(fs.getLanguage(), fs.getCountry(), null));
+            if (parent == null) {
+                parent = getFormSets().get(buildLocale(fs.getLanguage(), null, null));
+                if (parent == null) {
+                    parent = defaultFormSet;
+                }
+            }
+        }
+        return parent;
+    }
+
+    /**
+     * Gets a <code>ValidatorAction</code> based on it's name.
+     * @param key The validator action key.
+     * @return The validator action.
+     */
+    public ValidatorAction getValidatorAction(final String key) {
+        return getActions().get(key);
+    }
+
+    /**
+     * Gets an unmodifiable <code>Map</code> of the <code>ValidatorAction</code>s.
+     * @return Map of validator actions.
+     */
+    public Map<String, ValidatorAction> getValidatorActions() {
+        return Collections.unmodifiableMap(getActions());
+    }
+
+    /**
+     *  Initialize the digester.
+     */
+    private Digester initDigester() {
+        URL rulesUrl = this.getClass().getResource(VALIDATOR_RULES);
+        if (rulesUrl == null) {
+            // Fix for Issue# VALIDATOR-195
+            rulesUrl = ValidatorResources.class.getResource(VALIDATOR_RULES);
+        }
+        if (getLog().isDebugEnabled()) {
+            getLog().debug("Loading rules from '" + rulesUrl + "'");
+        }
+        final Digester digester = DigesterLoader.createDigester(rulesUrl);
+        digester.setNamespaceAware(true);
+        digester.setValidating(true);
+        digester.setUseContextClassLoader(true);
+
+        // Add rules for arg0-arg3 elements
+        addOldArgRules(digester);
+
+        // register DTDs
+        for (int i = 0; i < REGISTRATIONS.length; i += 2) {
+            final URL url = this.getClass().getResource(REGISTRATIONS[i + 1]);
+            if (url != null) {
+                digester.register(REGISTRATIONS[i], url.toString());
+            }
+        }
+        return digester;
+    }
+
+    /**
      * Process the <code>ValidatorResources</code> object. Currently sets the
      * <code>FastHashMap</code> s to the 'fast' mode and call the processes
      * all other resources. <strong>Note </strong>: The framework calls this
@@ -524,7 +611,7 @@
      * <code>FormSet</code>.</p>
      */
     private void processForms() {
-        if (defaultFormSet == null) {// it isn't mandatory to have a
+        if (defaultFormSet == null) { // it isn't mandatory to have a
             // default formset
             defaultFormSet = new FormSet();
         }
@@ -543,106 +630,4 @@
         }
     }
 
-    /**
-     * Finds the given formSet's parent. ex: A formSet with locale en_UK_TEST1
-     * has a direct parent in the formSet with locale en_UK. If it doesn't
-     * exist, find the formSet with locale en, if no found get the
-     * defaultFormSet.
-     *
-     * @param fs
-     *            the formSet we want to get the parent from
-     * @return fs's parent
-     */
-    private FormSet getParent(final FormSet fs) {
-
-        FormSet parent = null;
-        if (fs.getType() == FormSet.LANGUAGE_FORMSET) {
-            parent = defaultFormSet;
-        } else if (fs.getType() == FormSet.COUNTRY_FORMSET) {
-            parent = getFormSets().get(buildLocale(fs.getLanguage(),
-                    null, null));
-            if (parent == null) {
-                parent = defaultFormSet;
-            }
-        } else if (fs.getType() == FormSet.VARIANT_FORMSET) {
-            parent = getFormSets().get(buildLocale(fs.getLanguage(), fs
-                    .getCountry(), null));
-            if (parent == null) {
-                parent = getFormSets().get(buildLocale(fs.getLanguage(),
-                        null, null));
-                if (parent == null) {
-                    parent = defaultFormSet;
-                }
-            }
-        }
-        return parent;
-    }
-
-    /**
-     * <p>Gets a <code>FormSet</code> based on the language, country
-     *    and variant.</p>
-     * @param language The locale's language.
-     * @param country The locale's country.
-     * @param variant The locale's language variant.
-     * @return The FormSet for a locale.
-     * @since 1.2
-     */
-    FormSet getFormSet(final String language, final String country, final String variant) {
-
-        final String key = buildLocale(language, country, variant);
-
-        if (key.isEmpty()) {
-            return defaultFormSet;
-        }
-
-        return getFormSets().get(key);
-    }
-
-    /**
-     * Returns a Map of String locale keys to Lists of their FormSets.
-     * @return Map of Form sets
-     * @since 1.2.0
-     */
-    @SuppressWarnings("unchecked") // FastHashMap is not generic
-    protected Map<String, FormSet> getFormSets() {
-        return hFormSets;
-    }
-
-    /**
-     * Returns a Map of String constant names to their String values.
-     * @return Map of Constants
-     * @since 1.2.0
-     */
-    @SuppressWarnings("unchecked") // FastHashMap is not generic
-    protected Map<String, String> getConstants() {
-        return hConstants;
-    }
-
-    /**
-     * Returns a Map of String ValidatorAction names to their ValidatorAction.
-     * @return Map of Validator Actions
-     * @since 1.2.0
-     */
-    @SuppressWarnings("unchecked") // FastHashMap is not generic
-    protected Map<String, ValidatorAction> getActions() {
-        return hActions;
-    }
-
-    /**
-     * Accessor method for Log instance.
-     *
-     * The Log instance variable is transient and
-     * accessing it through this method ensures it
-     * is re-initialized when this instance is
-     * de-serialized.
-     *
-     * @return The Log instance.
-     */
-    private Log getLog() {
-        if (log == null) {
-            log =  LogFactory.getLog(ValidatorResources.class);
-        }
-        return log;
-    }
-
 }
diff --git a/src/main/java/org/apache/commons/validator/ValidatorResult.java b/src/main/java/org/apache/commons/validator/ValidatorResult.java
index a700d3e..87c41ca 100644
--- a/src/main/java/org/apache/commons/validator/ValidatorResult.java
+++ b/src/main/java/org/apache/commons/validator/ValidatorResult.java
@@ -29,6 +29,80 @@
 //TODO mutable non-private fields
 public class ValidatorResult implements Serializable {
 
+    /**
+     * Contains the status of the validation.
+     */
+    protected static class ResultStatus implements Serializable {
+
+        private static final long serialVersionUID = 4076665918535320007L;
+
+        /** Whether or not the validation passed. */
+        private boolean valid;
+
+        /** Result returned by a validation method. */
+        private Object result;
+
+       /**
+        * Constructs a Result status.
+        * @param valid Whether the validator passed or failed.
+        * @param result Value returned by the validator.
+        */
+        public ResultStatus(final boolean valid, final Object result) {
+            this.valid = valid;
+            this.result = result;
+        }
+        /**
+         * Provided for backwards binary compatibility only.
+         *
+         * @param ignored ignored by this method
+         * @param valid Whether the validator passed or failed.
+         * @param result Value returned by the validator.
+         *
+         * @deprecated Use {@code ResultStatus(boolean, Object)} instead
+         */
+        @Deprecated
+        public ResultStatus(final ValidatorResult ignored, final boolean valid, final Object result) {
+            this(valid, result);
+        }
+
+        /**
+         * Gets the result returned by a validation method.
+         * This can be used to retrieve to the correctly
+         * typed value of a date validation for example.
+         * @return The value returned by the validation.
+         */
+        public Object getResult() {
+            return result;
+        }
+
+        /**
+         * Tests whether or not the validation passed.
+         * @return true if the result was good.
+         */
+        public boolean isValid() {
+            return valid;
+        }
+
+        /**
+         * Sets the result returned by a validation method.
+         * This can be used to retrieve to the correctly
+         * typed value of a date validation for example.
+         * @param result The value returned by the validation.
+         */
+        public void setResult(final Object result) {
+            this.result = result;
+        }
+
+        /**
+         * Sets whether or not the validation passed.
+         * @param valid Whether the validation passed.
+         */
+        public void setValid(final boolean valid) {
+            this.valid = valid;
+        }
+
+    }
+
     private static final long serialVersionUID = -3713364681647250531L;
 
     /**
@@ -81,40 +155,11 @@
     }
 
     /**
-     * Indicate whether a specified validation passed.
-     * @param validatorName Name of the validator.
-     * @return true if the validation passed.
-     */
-    public boolean isValid(final String validatorName) {
-        final ResultStatus status = hAction.get(validatorName);
-        return (status == null) ? false : status.isValid();
-    }
-
-    /**
-     * Return the result of a validation.
-     * @param validatorName Name of the validator.
-     * @return The validation result.
-     */
-    public Object getResult(final String validatorName) {
-        final ResultStatus status = hAction.get(validatorName);
-        return (status == null) ? null : status.getResult();
-    }
-
-    /**
-     * Return an Iterator of the action names contained in this Result.
-     * @return The set of action names.
-     */
-    public Iterator<String> getActions() {
-        return Collections.unmodifiableMap(hAction).keySet().iterator();
-    }
-
-    /**
-     * Return a Map of the validator actions in this Result.
+     * Gets a Map of the validator actions in this Result.
      * @return Map of validator actions.
      * @deprecated Use getActions() to return the set of actions
      *             the isValid(name) and getResult(name) methods
      *             to determine the contents of ResultStatus.
-     *
      */
     @Deprecated
     public Map<String, ResultStatus> getActionMap() {
@@ -122,6 +167,14 @@
     }
 
     /**
+     * Gets an Iterator of the action names contained in this Result.
+     * @return The set of action names.
+     */
+    public Iterator<String> getActions() {
+        return Collections.unmodifiableMap(hAction).keySet().iterator();
+    }
+
+    /**
      * Returns the Field that was validated.
      * @return The Field associated with this result.
      */
@@ -130,74 +183,23 @@
     }
 
     /**
-     * Contains the status of the validation.
+     * Gets the result of a validation.
+     * @param validatorName Name of the validator.
+     * @return The validation result.
      */
-    protected static class ResultStatus implements Serializable {
+    public Object getResult(final String validatorName) {
+        final ResultStatus status = hAction.get(validatorName);
+        return status == null ? null : status.getResult();
+    }
 
-        private static final long serialVersionUID = 4076665918535320007L;
-
-        private boolean valid;
-        private Object result;
-
-       /**
-        * Construct a Result status.
-        * @param valid Whether the validator passed or failed.
-        * @param result Value returned by the validator.
-        */
-        public ResultStatus(final boolean valid, final Object result) {
-            this.valid = valid;
-            this.result = result;
-        }
-        /**
-         * Provided for backwards binary compatibility only.
-         *
-         * @param ignored ignored by this method
-         * @param valid Whether the validator passed or failed.
-         * @param result Value returned by the validator.
-         *
-         * @deprecated Use {@code ResultStatus(boolean, Object)} instead
-         */
-        @Deprecated
-        public ResultStatus(final ValidatorResult ignored, final boolean valid, final Object result) {
-            this(valid, result);
-        }
-
-        /**
-         * Tests whether or not the validation passed.
-         * @return true if the result was good.
-         */
-        public boolean isValid() {
-            return valid;
-        }
-
-        /**
-         * Sets whether or not the validation passed.
-         * @param valid Whether the validation passed.
-         */
-        public void setValid(final boolean valid) {
-            this.valid = valid;
-        }
-
-        /**
-         * Gets the result returned by a validation method.
-         * This can be used to retrieve to the correctly
-         * typed value of a date validation for example.
-         * @return The value returned by the validation.
-         */
-        public Object getResult() {
-            return result;
-        }
-
-        /**
-         * Sets the result returned by a validation method.
-         * This can be used to retrieve to the correctly
-         * typed value of a date validation for example.
-         * @param result The value returned by the validation.
-         */
-        public void setResult(final Object result) {
-            this.result = result;
-        }
-
+    /**
+     * Indicate whether a specified validation passed.
+     * @param validatorName Name of the validator.
+     * @return true if the validation passed.
+     */
+    public boolean isValid(final String validatorName) {
+        final ResultStatus status = hAction.get(validatorName);
+        return status == null ? false : status.isValid();
     }
 
 }
\ No newline at end of file
diff --git a/src/main/java/org/apache/commons/validator/ValidatorResults.java b/src/main/java/org/apache/commons/validator/ValidatorResults.java
index 351c318..1bddbbb 100644
--- a/src/main/java/org/apache/commons/validator/ValidatorResults.java
+++ b/src/main/java/org/apache/commons/validator/ValidatorResults.java
@@ -38,15 +38,6 @@
     protected Map<String, ValidatorResult> hResults = new HashMap<>();
 
     /**
-     * Merge another ValidatorResults into mine.
-     *
-     * @param results ValidatorResults to merge.
-     */
-    public void merge(final ValidatorResults results) {
-        this.hResults.putAll(results.hResults);
-    }
-
-    /**
      * Add a the result of a validator action.
      *
      * @param field The field validated.
@@ -89,31 +80,7 @@
     }
 
     /**
-     * Return <code>true</code> if there are no messages recorded
-     * in this collection, or <code>false</code> otherwise.
-     *
-     * @return Whether these results are empty.
-     */
-    public boolean isEmpty() {
-        return this.hResults.isEmpty();
-    }
-
-    /**
-     * Gets the <code>ValidatorResult</code> associated
-     * with the key passed in.  The key the <code>ValidatorResult</code>
-     * is stored under is the <code>Field</code>'s getKey method.
-     *
-     * @param key The key generated from <code>Field</code> (this is often just
-     * the field name).
-     *
-     * @return The result of a specified key.
-     */
-    public ValidatorResult getValidatorResult(final String key) {
-        return this.hResults.get(key);
-    }
-
-    /**
-     * Return the set of property names for which at least one message has
+     * Gets the set of property names for which at least one message has
      * been recorded.
      * @return An unmodifiable Set of the property names.
      */
@@ -122,7 +89,7 @@
     }
 
     /**
-     * Get a <code>Map</code> of any <code>Object</code>s returned from
+     * Gets a <code>Map</code> of any <code>Object</code>s returned from
      * validation routines.
      *
      * @return Map of objections returned by validators.
@@ -146,4 +113,37 @@
         return results;
     }
 
+    /**
+     * Gets the <code>ValidatorResult</code> associated
+     * with the key passed in.  The key the <code>ValidatorResult</code>
+     * is stored under is the <code>Field</code>'s getKey method.
+     *
+     * @param key The key generated from <code>Field</code> (this is often just
+     * the field name).
+     *
+     * @return The result of a specified key.
+     */
+    public ValidatorResult getValidatorResult(final String key) {
+        return this.hResults.get(key);
+    }
+
+    /**
+     * Gets {@code true} if there are no messages recorded
+     * in this collection, or {@code false} otherwise.
+     *
+     * @return Whether these results are empty.
+     */
+    public boolean isEmpty() {
+        return this.hResults.isEmpty();
+    }
+
+    /**
+     * Merge another ValidatorResults into mine.
+     *
+     * @param results ValidatorResults to merge.
+     */
+    public void merge(final ValidatorResults results) {
+        this.hResults.putAll(results.hResults);
+    }
+
 }
diff --git a/src/main/java/org/apache/commons/validator/Var.java b/src/main/java/org/apache/commons/validator/Var.java
index a66bdad..f00761a 100644
--- a/src/main/java/org/apache/commons/validator/Var.java
+++ b/src/main/java/org/apache/commons/validator/Var.java
@@ -78,10 +78,10 @@
 
     /**
      * Constructs a variable with a specified name, value
-     * and Javascript type.
+     * and JavaScript type.
      * @param name Variable name.
      * @param value Variable value.
-     * @param jsType Variable Javascript type.
+     * @param jsType Variable JavaScript type.
      */
     public Var(final String name, final String value, final String jsType) {
         this.name = name;
@@ -90,90 +90,6 @@
     }
 
     /**
-     * Gets the name of the variable.
-     * @return The name of the variable.
-     */
-    public String getName() {
-        return this.name;
-    }
-
-    /**
-     * Sets the name of the variable.
-     * @param name The name of the variable.
-     */
-    public void setName(final String name) {
-        this.name = name;
-    }
-
-    /**
-     * Gets the value of the variable.
-     * @return The value of the variable.
-     */
-    public String getValue() {
-        return this.value;
-    }
-
-    /**
-     * Sets the value of the variable.
-     * @param value The value of the variable.
-     */
-    public void setValue(final String value) {
-        this.value = value;
-    }
-
-    /**
-     * Tests whether or not the value is a resource key or literal value.
-     * @return <code>true</code> if value is a resource key.
-     * @since 1.2.0
-     */
-    public boolean isResource() {
-        return this.resource;
-    }
-
-    /**
-     * Sets whether or not the value is a resource.
-     * @param resource If true indicates the value is a resource.
-     * @since 1.2.0
-     */
-    public void setResource(final boolean resource) {
-        this.resource = resource;
-    }
-
-    /**
-     * Returns the resource bundle name.
-     * @return The bundle name.
-     * @since 1.2.0
-     */
-    public String getBundle() {
-        return this.bundle;
-    }
-
-    /**
-     * Sets the resource bundle name.
-     * @param bundle The new bundle name.
-     * @since 1.2.0
-     */
-    public void setBundle(final String bundle) {
-        this.bundle = bundle;
-    }
-
-    /**
-     * Gets the JavaScript type of the variable.
-     * @return The Javascript type of the variable.
-     */
-    public String getJsType() {
-        return this.jsType;
-    }
-
-    /**
-     * Sets the JavaScript type of the variable.
-     * @param jsType The Javascript type of the variable.
-     */
-    public void setJsType(final String jsType) {
-        this.jsType = jsType;
-    }
-
-    /**
      * Creates and returns a copy of this object.
      * @return A copy of the variable.
      */
@@ -182,12 +98,96 @@
         try {
             return super.clone();
 
-        } catch(final CloneNotSupportedException e) {
-            throw new RuntimeException(e.toString());
+        } catch (final CloneNotSupportedException e) {
+            throw new UnsupportedOperationException(e.toString(), e);
         }
     }
 
     /**
+     * Returns the resource bundle name.
+     * @return The bundle name.
+     * @since 1.2.0
+     */
+    public String getBundle() {
+        return this.bundle;
+    }
+
+    /**
+     * Gets the JavaScript type of the variable.
+     * @return The JavaScript type of the variable.
+     */
+    public String getJsType() {
+        return this.jsType;
+    }
+
+    /**
+     * Gets the name of the variable.
+     * @return The name of the variable.
+     */
+    public String getName() {
+        return this.name;
+    }
+
+    /**
+     * Gets the value of the variable.
+     * @return The value of the variable.
+     */
+    public String getValue() {
+        return this.value;
+    }
+
+    /**
+     * Tests whether or not the value is a resource key or literal value.
+     * @return {@code true} if value is a resource key.
+     * @since 1.2.0
+     */
+    public boolean isResource() {
+        return this.resource;
+    }
+
+    /**
+     * Sets the resource bundle name.
+     * @param bundle The new bundle name.
+     * @since 1.2.0
+     */
+    public void setBundle(final String bundle) {
+        this.bundle = bundle;
+    }
+
+    /**
+     * Sets the JavaScript type of the variable.
+     * @param jsType The JavaScript type of the variable.
+     */
+    public void setJsType(final String jsType) {
+        this.jsType = jsType;
+    }
+
+    /**
+     * Sets the name of the variable.
+     * @param name The name of the variable.
+     */
+    public void setName(final String name) {
+        this.name = name;
+    }
+
+    /**
+     * Sets whether or not the value is a resource.
+     * @param resource If true indicates the value is a resource.
+     * @since 1.2.0
+     */
+    public void setResource(final boolean resource) {
+        this.resource = resource;
+    }
+
+    /**
+     * Sets the value of the variable.
+     * @param value The value of the variable.
+     */
+    public void setValue(final String value) {
+        this.value = value;
+    }
+
+    /**
      * Returns a string representation of the object.
      * @return A string representation of the variable.
      */
diff --git a/src/main/java/org/apache/commons/validator/package-info.java b/src/main/java/org/apache/commons/validator/package-info.java
index d8d7a99..10373b1 100644
--- a/src/main/java/org/apache/commons/validator/package-info.java
+++ b/src/main/java/org/apache/commons/validator/package-info.java
@@ -20,7 +20,7 @@
  *
  * <a id="doc.Description"></a>
  * <div>
- * <a href="http://commons.apache.org/validator/dependencies.html">[Dependencies]</a>
+ * <a href="https://commons.apache.org/validator/dependencies.html">[Dependencies]</a>
  * <a href="#doc.Intro">[Introduction]</a>
  * <a href="#doc.Overview">[Overview]</a>
  * <a href="#doc.Resources">[Resources]</a>
@@ -58,7 +58,7 @@
  * what method and class will be called to perform the validation
  * for a required field.  Validation rules can be grouped together
  * based on locale and a JavaBean/Form that the rules are associated
- * with.  The framework has basic support for user defined constants
+ * with.  The framework has basic support for user-defined constants
  * which can be used in some field attributes.
  * </p>
  * <p>
@@ -66,7 +66,7 @@
  * them abstracted from JavaBean you are validating.  The
  * property reference to a field supports nested properties
  * using the Apache Commons BeanUtils
- * (http://commons.apache.org/beanutils/) package.
+ * (https://commons.apache.org/beanutils/) package.
  * Error messages and the arguments for error messages can be
  * associated with a fields validation.
  * </p>
diff --git a/src/main/java/org/apache/commons/validator/routines/AbstractCalendarValidator.java b/src/main/java/org/apache/commons/validator/routines/AbstractCalendarValidator.java
index 18c3d6a..324a570 100644
--- a/src/main/java/org/apache/commons/validator/routines/AbstractCalendarValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/AbstractCalendarValidator.java
@@ -36,15 +36,21 @@
 
     private static final long serialVersionUID = -1410008585975827379L;
 
+    /**
+     * The date style to use for Locale validation.
+     */
     private final int dateStyle;
 
+    /**
+     * The time style to use for Locale validation.
+     */
     private final int timeStyle;
 
     /**
-     * Construct an instance with the specified <i>strict</i>,
+     * Constructs an instance with the specified <i>strict</i>,
      * <i>time</i> and <i>date</i> style parameters.
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param dateStyle the date style to use for Locale validation.
      * @param timeStyle the time style to use for Locale validation.
@@ -56,44 +62,187 @@
     }
 
     /**
-     * <p>Validate using the specified <code>Locale</code>.
+     * <p>Compares the field from two calendars indicating whether the field for the
+     *    first calendar is equal to, less than or greater than the field from the
+     *    second calendar.
      *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to format the value.
-     * @param locale The locale to use for the Format, defaults to the default
-     * @return <code>true</code> if the value is valid.
+     * @param value The Calendar value.
+     * @param compare The <code>Calendar</code> to check the value against.
+     * @param field The field to compare for the calendars.
+     * @return Zero if the first calendar's field is equal to the seconds, -1
+     *         if it is less than the seconds or +1 if it is greater than the seconds.
+     */
+    private int calculateCompareResult(final Calendar value, final Calendar compare, final int field) {
+        final int difference = value.get(field) - compare.get(field);
+        if (difference < 0) {
+            return -1;
+        }
+        if (difference > 0) {
+            return 1;
+        }
+        return 0;
+    }
+
+    /**
+     * <p>Calculate the quarter for the specified Calendar.</p>
+     *
+     * @param calendar The Calendar value.
+     * @param monthOfFirstQuarter The  month that the first quarter starts.
+     * @return The calculated quarter.
+     */
+    private int calculateQuarter(final Calendar calendar, final int monthOfFirstQuarter) {
+        // Add Year
+        int year = calendar.get(Calendar.YEAR);
+
+        final int month = calendar.get(Calendar.MONTH) + 1;
+        final int relativeMonth = month >= monthOfFirstQuarter
+                          ? month - monthOfFirstQuarter
+                          : month + 12 - monthOfFirstQuarter; // CHECKSTYLE IGNORE MagicNumber
+        final int quarter = relativeMonth / 3 + 1; // CHECKSTYLE IGNORE MagicNumber
+        // adjust the year if the quarter doesn't start in January
+        if (month < monthOfFirstQuarter) {
+            --year;
+        }
+        return year * 10 + quarter; // CHECKSTYLE IGNORE MagicNumber
+    }
+
+    /**
+     * <p>Compares a calendar value to another, indicating whether it is
+     *    equal, less then or more than at a specified level.</p>
+     *
+     * @param value The Calendar value.
+     * @param compare The <code>Calendar</code> to check the value against.
+     * @param field The field <i>level</i> to compare to - e.g. specifying
+     *        <code>Calendar.MONTH</code> will compare the year and month
+     *        portions of the calendar.
+     * @return Zero if the first value is equal to the second, -1
+     *         if it is less than the second or +1 if it is greater than the second.
+     */
+    protected int compare(final Calendar value, final Calendar compare, final int field) {
+
+        int result;
+
+        // Compare Year
+        result = calculateCompareResult(value, compare, Calendar.YEAR);
+        if (result != 0 || field == Calendar.YEAR) {
+            return result;
+        }
+
+        // Compare Week of Year
+        if (field == Calendar.WEEK_OF_YEAR) {
+            return calculateCompareResult(value, compare, Calendar.WEEK_OF_YEAR);
+        }
+
+        // Compare Day of the Year
+        if (field == Calendar.DAY_OF_YEAR) {
+            return calculateCompareResult(value, compare, Calendar.DAY_OF_YEAR);
+        }
+
+        // Compare Month
+        result = calculateCompareResult(value, compare, Calendar.MONTH);
+        if (result != 0 || field == Calendar.MONTH) {
+            return result;
+        }
+
+        // Compare Week of Month
+        if (field == Calendar.WEEK_OF_MONTH) {
+            return calculateCompareResult(value, compare, Calendar.WEEK_OF_MONTH);
+        }
+
+        // Compare Date
+        result = calculateCompareResult(value, compare, Calendar.DATE);
+        if (result != 0 || field == Calendar.DATE ||
+                          field == Calendar.DAY_OF_WEEK ||
+                          field == Calendar.DAY_OF_WEEK_IN_MONTH) {
+            return result;
+        }
+
+        // Compare Time fields
+        return compareTime(value, compare, field);
+
+    }
+
+    /**
+     * <p>Compares a calendar's quarter value to another, indicating whether it is
+     *    equal, less then or more than the specified quarter.</p>
+     *
+     * @param value The Calendar value.
+     * @param compare The <code>Calendar</code> to check the value against.
+     * @param monthOfFirstQuarter The  month that the first quarter starts.
+     * @return Zero if the first quarter is equal to the second, -1
+     *         if it is less than the second or +1 if it is greater than the second.
+     */
+    protected int compareQuarters(final Calendar value, final Calendar compare, final int monthOfFirstQuarter) {
+        final int valueQuarter = calculateQuarter(value, monthOfFirstQuarter);
+        final int compareQuarter = calculateQuarter(compare, monthOfFirstQuarter);
+        if (valueQuarter < compareQuarter) {
+            return -1;
+        }
+        if (valueQuarter > compareQuarter) {
+            return 1;
+        }
+        return 0;
+    }
+
+    /**
+     * <p>Compares a calendar time value to another, indicating whether it is
+     *    equal, less then or more than at a specified level.</p>
+     *
+     * @param value The Calendar value.
+     * @param compare The <code>Calendar</code> to check the value against.
+     * @param field The field <i>level</i> to compare to - e.g. specifying
+     *        <code>Calendar.MINUTE</code> will compare the hours and minutes
+     *        portions of the calendar.
+     * @return Zero if the first value is equal to the second, -1
+     *         if it is less than the second or +1 if it is greater than the second.
+     */
+    protected int compareTime(final Calendar value, final Calendar compare, final int field) {
+
+        int result;
+
+        // Compare Hour
+        result = calculateCompareResult(value, compare, Calendar.HOUR_OF_DAY);
+        if (result != 0 || field == Calendar.HOUR || field == Calendar.HOUR_OF_DAY) {
+            return result;
+        }
+
+        // Compare Minute
+        result = calculateCompareResult(value, compare, Calendar.MINUTE);
+        if (result != 0 || field == Calendar.MINUTE) {
+            return result;
+        }
+
+        // Compare Second
+        result = calculateCompareResult(value, compare, Calendar.SECOND);
+        if (result != 0 || field == Calendar.SECOND) {
+            return result;
+        }
+
+        // Compare Milliseconds
+        if (field == Calendar.MILLISECOND) {
+            return calculateCompareResult(value, compare, Calendar.MILLISECOND);
+        }
+
+        throw new IllegalArgumentException("Invalid field: " + field);
+
+    }
+
+    /**
+     * <p>Format a value with the specified <code>DateFormat</code>.</p>
+     *
+     * @param value The value to be formatted.
+     * @param formatter The Format to use.
+     * @return The formatted value.
      */
     @Override
-    public boolean isValid(final String value, final String pattern, final Locale locale) {
-        final Object parsedValue = parse(value, pattern, locale, (TimeZone)null);
-        return (parsedValue == null ? false : true);
-    }
-
-    /**
-     * <p>Format an object into a <code>String</code> using
-     * the default Locale.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param timeZone The Time Zone used to format the date,
-     *  system default if null (unless value is a <code>Calendar</code>.
-     * @return The value formatted as a <code>String</code>.
-     */
-    public String format(final Object value, final TimeZone timeZone) {
-        return format(value, (String)null, (Locale)null, timeZone);
-    }
-
-    /**
-     * <p>Format an object into a <code>String</code> using
-     * the specified pattern.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to format the value.
-     * @param timeZone The Time Zone used to format the date,
-     *  system default if null (unless value is a <code>Calendar</code>.
-     * @return The value formatted as a <code>String</code>.
-     */
-    public String format(final Object value, final String pattern, final TimeZone timeZone) {
-        return format(value, pattern, (Locale)null, timeZone);
+    protected String format(Object value, final Format formatter) {
+        if (value == null) {
+            return null;
+        }
+        if (value instanceof Calendar) {
+            value = ((Calendar)value).getTime();
+        }
+        return formatter.format(value);
     }
 
     /**
@@ -146,82 +295,30 @@
     }
 
     /**
-     * <p>Format a value with the specified <code>DateFormat</code>.</p>
-     *
-     * @param value The value to be formatted.
-     * @param formatter The Format to use.
-     * @return The formatted value.
-     */
-    @Override
-    protected String format(Object value, final Format formatter) {
-        if (value == null) {
-            return null;
-        }
-        if (value instanceof Calendar) {
-            value = ((Calendar)value).getTime();
-        }
-        return formatter.format(value);
-    }
-
-    /**
-     * <p>Checks if the value is valid against a specified pattern.</p>
+     * <p>Format an object into a <code>String</code> using
+     * the specified pattern.</p>
      *
      * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @param timeZone The Time Zone used to parse the date, system default if null.
-     * @return The parsed value if valid or <code>null</code> if invalid.
+     * @param pattern The pattern used to format the value.
+     * @param timeZone The Time Zone used to format the date,
+     *  system default if null (unless value is a <code>Calendar</code>.
+     * @return The value formatted as a <code>String</code>.
      */
-    protected Object parse(String value, final String pattern, final Locale locale, final TimeZone timeZone) {
-
-        value = (value == null ? null : value.trim());
-        if (value == null || value.isEmpty()) {
-            return null;
-        }
-        final DateFormat formatter = (DateFormat)getFormat(pattern, locale);
-        if (timeZone != null) {
-            formatter.setTimeZone(timeZone);
-        }
-        return parse(value, formatter);
-
+    public String format(final Object value, final String pattern, final TimeZone timeZone) {
+        return format(value, pattern, (Locale)null, timeZone);
     }
 
     /**
-     * <p>Process the parsed value, performing any further validation
-     *    and type conversion required.</p>
+     * <p>Format an object into a <code>String</code> using
+     * the default Locale.</p>
      *
-     * @param value The parsed object created.
-     * @param formatter The Format used to parse the value with.
-     * @return The parsed value converted to the appropriate type
-     *         if valid or <code>null</code> if invalid.
+     * @param value The value validation is being performed on.
+     * @param timeZone The Time Zone used to format the date,
+     *  system default if null (unless value is a <code>Calendar</code>.
+     * @return The value formatted as a <code>String</code>.
      */
-    @Override
-    protected abstract Object processParsedValue(Object value, Format formatter);
-
-    /**
-     * <p>Returns a <code>DateFormat</code> for the specified <i>pattern</i>
-     *    and/or <code>Locale</code>.</p>
-     *
-     * @param pattern The pattern used to validate the value against or
-     *        <code>null</code> to use the default for the <code>Locale</code>.
-     * @param locale The locale to use for the currency format, system default if null.
-     * @return The <code>DateFormat</code> to created.
-     */
-    @Override
-    protected Format getFormat(final String pattern, final Locale locale) {
-        DateFormat formatter;
-        final boolean usePattern = pattern != null && !pattern.isEmpty();
-        if (!usePattern) {
-            formatter = (DateFormat)getFormat(locale);
-        } else if (locale == null) {
-            formatter = new SimpleDateFormat(pattern);
-        } else {
-            final DateFormatSymbols symbols = new DateFormatSymbols(locale);
-            formatter = new SimpleDateFormat(pattern, symbols);
-        }
-        formatter.setLenient(false);
-        return formatter;
+    public String format(final Object value, final TimeZone timeZone) {
+        return format(value, (String)null, (Locale)null, timeZone);
     }
 
     /**
@@ -260,168 +357,77 @@
     }
 
     /**
-     * <p>Compares a calendar value to another, indicating whether it is
-     *    equal, less then or more than at a specified level.</p>
+     * <p>Returns a <code>DateFormat</code> for the specified <i>pattern</i>
+     *    and/or <code>Locale</code>.</p>
      *
-     * @param value The Calendar value.
-     * @param compare The <code>Calendar</code> to check the value against.
-     * @param field The field <i>level</i> to compare to - e.g. specifying
-     *        <code>Calendar.MONTH</code> will compare the year and month
-     *        portions of the calendar.
-     * @return Zero if the first value is equal to the second, -1
-     *         if it is less than the second or +1 if it is greater than the second.
+     * @param pattern The pattern used to validate the value against or
+     *        {@code null} to use the default for the <code>Locale</code>.
+     * @param locale The locale to use for the currency format, system default if null.
+     * @return The <code>DateFormat</code> to created.
      */
-    protected int compare(final Calendar value, final Calendar compare, final int field) {
-
-        int result;
-
-        // Compare Year
-        result = calculateCompareResult(value, compare, Calendar.YEAR);
-        if (result != 0 || field == Calendar.YEAR) {
-            return result;
+    @Override
+    protected Format getFormat(final String pattern, final Locale locale) {
+        DateFormat formatter;
+        final boolean usePattern = pattern != null && !pattern.isEmpty();
+        if (!usePattern) {
+            formatter = (DateFormat)getFormat(locale);
+        } else if (locale == null) {
+            formatter = new SimpleDateFormat(pattern);
+        } else {
+            final DateFormatSymbols symbols = new DateFormatSymbols(locale);
+            formatter = new SimpleDateFormat(pattern, symbols);
         }
+        formatter.setLenient(false);
+        return formatter;
+    }
 
-        // Compare Week of Year
-        if (field == Calendar.WEEK_OF_YEAR) {
-            return calculateCompareResult(value, compare, Calendar.WEEK_OF_YEAR);
+    /**
+     * <p>Validate using the specified <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to format the value.
+     * @param locale The locale to use for the Format, defaults to the default
+     * @return {@code true} if the value is valid.
+     */
+    @Override
+    public boolean isValid(final String value, final String pattern, final Locale locale) {
+        final Object parsedValue = parse(value, pattern, locale, (TimeZone)null);
+        return parsedValue == null ? false : true;
+    }
+
+    /**
+     * <p>Checks if the value is valid against a specified pattern.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @param timeZone The Time Zone used to parse the date, system default if null.
+     * @return The parsed value if valid or {@code null} if invalid.
+     */
+    protected Object parse(String value, final String pattern, final Locale locale, final TimeZone timeZone) {
+
+        value = value == null ? null : value.trim();
+        if (value == null || value.isEmpty()) {
+            return null;
         }
-
-        // Compare Day of the Year
-        if (field == Calendar.DAY_OF_YEAR) {
-            return calculateCompareResult(value, compare, Calendar.DAY_OF_YEAR);
+        final DateFormat formatter = (DateFormat)getFormat(pattern, locale);
+        if (timeZone != null) {
+            formatter.setTimeZone(timeZone);
         }
-
-        // Compare Month
-        result = calculateCompareResult(value, compare, Calendar.MONTH);
-        if (result != 0 || field == Calendar.MONTH) {
-            return result;
-        }
-
-        // Compare Week of Month
-        if (field == Calendar.WEEK_OF_MONTH) {
-            return calculateCompareResult(value, compare, Calendar.WEEK_OF_MONTH);
-        }
-
-        // Compare Date
-        result = calculateCompareResult(value, compare, Calendar.DATE);
-        if (result != 0 || (field == Calendar.DATE ||
-                          field == Calendar.DAY_OF_WEEK ||
-                          field == Calendar.DAY_OF_WEEK_IN_MONTH)) {
-            return result;
-        }
-
-        // Compare Time fields
-        return compareTime(value, compare, field);
+        return parse(value, formatter);
 
     }
 
     /**
-     * <p>Compares a calendar time value to another, indicating whether it is
-     *    equal, less then or more than at a specified level.</p>
+     * <p>Process the parsed value, performing any further validation
+     *    and type conversion required.</p>
      *
-     * @param value The Calendar value.
-     * @param compare The <code>Calendar</code> to check the value against.
-     * @param field The field <i>level</i> to compare to - e.g. specifying
-     *        <code>Calendar.MINUTE</code> will compare the hours and minutes
-     *        portions of the calendar.
-     * @return Zero if the first value is equal to the second, -1
-     *         if it is less than the second or +1 if it is greater than the second.
+     * @param value The parsed object created.
+     * @param formatter The Format used to parse the value with.
+     * @return The parsed value converted to the appropriate type
+     *         if valid or {@code null} if invalid.
      */
-    protected int compareTime(final Calendar value, final Calendar compare, final int field) {
-
-        int result;
-
-        // Compare Hour
-        result = calculateCompareResult(value, compare, Calendar.HOUR_OF_DAY);
-        if (result != 0 || (field == Calendar.HOUR || field == Calendar.HOUR_OF_DAY)) {
-            return result;
-        }
-
-        // Compare Minute
-        result = calculateCompareResult(value, compare, Calendar.MINUTE);
-        if (result != 0 || field == Calendar.MINUTE) {
-            return result;
-        }
-
-        // Compare Second
-        result = calculateCompareResult(value, compare, Calendar.SECOND);
-        if (result != 0 || field == Calendar.SECOND) {
-            return result;
-        }
-
-        // Compare Milliseconds
-        if (field == Calendar.MILLISECOND) {
-            return calculateCompareResult(value, compare, Calendar.MILLISECOND);
-        }
-
-        throw new IllegalArgumentException("Invalid field: " + field);
-
-    }
-
-    /**
-     * <p>Compares a calendar's quarter value to another, indicating whether it is
-     *    equal, less then or more than the specified quarter.</p>
-     *
-     * @param value The Calendar value.
-     * @param compare The <code>Calendar</code> to check the value against.
-     * @param monthOfFirstQuarter The  month that the first quarter starts.
-     * @return Zero if the first quarter is equal to the second, -1
-     *         if it is less than the second or +1 if it is greater than the second.
-     */
-    protected int compareQuarters(final Calendar value, final Calendar compare, final int monthOfFirstQuarter) {
-        final int valueQuarter   = calculateQuarter(value, monthOfFirstQuarter);
-        final int compareQuarter = calculateQuarter(compare, monthOfFirstQuarter);
-        if (valueQuarter < compareQuarter) {
-            return -1;
-        }
-        if (valueQuarter > compareQuarter) {
-            return 1;
-        }
-        return 0;
-    }
-
-    /**
-     * <p>Calculate the quarter for the specified Calendar.</p>
-     *
-     * @param calendar The Calendar value.
-     * @param monthOfFirstQuarter The  month that the first quarter starts.
-     * @return The calculated quarter.
-     */
-    private int calculateQuarter(final Calendar calendar, final int monthOfFirstQuarter) {
-        // Add Year
-        int year = calendar.get(Calendar.YEAR);
-
-        final int month = (calendar.get(Calendar.MONTH) + 1);
-        final int relativeMonth = (month >= monthOfFirstQuarter)
-                          ? (month - monthOfFirstQuarter)
-                          : (month + (12 - monthOfFirstQuarter)); // CHECKSTYLE IGNORE MagicNumber
-        final int quarter = ((relativeMonth / 3) + 1); // CHECKSTYLE IGNORE MagicNumber
-        // adjust the year if the quarter doesn't start in January
-        if (month < monthOfFirstQuarter) {
-            --year;
-        }
-        return (year * 10) + quarter; // CHECKSTYLE IGNORE MagicNumber
-    }
-
-    /**
-     * <p>Compares the field from two calendars indicating whether the field for the
-     *    first calendar is equal to, less than or greater than the field from the
-     *    second calendar.
-     *
-     * @param value The Calendar value.
-     * @param compare The <code>Calendar</code> to check the value against.
-     * @param field The field to compare for the calendars.
-     * @return Zero if the first calendar's field is equal to the seconds, -1
-     *         if it is less than the seconds or +1 if it is greater than the seconds.
-     */
-    private int calculateCompareResult(final Calendar value, final Calendar compare, final int field) {
-        final int difference = value.get(field) - compare.get(field);
-        if (difference < 0) {
-            return -1;
-        }
-        if (difference > 0) {
-            return 1;
-        }
-        return 0;
-    }
+    @Override
+    protected abstract Object processParsedValue(Object value, Format formatter);
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/AbstractFormatValidator.java b/src/main/java/org/apache/commons/validator/routines/AbstractFormatValidator.java
index 2c62f03..6797a34 100644
--- a/src/main/java/org/apache/commons/validator/routines/AbstractFormatValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/AbstractFormatValidator.java
@@ -33,12 +33,15 @@
 
     private static final long serialVersionUID = -4690687565200568258L;
 
+    /**
+     * Whether to use strict format.
+     */
     private final boolean strict;
 
     /**
-     * Construct an instance with the specified strict setting.
+     * Constructs an instance with the specified strict setting.
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      */
     public AbstractFormatValidator(final boolean strict) {
@@ -46,69 +49,6 @@
     }
 
     /**
-     * <p>Indicates whether validated values should adhere
-     *    strictly to the <code>Format</code> used.</p>
-     *
-     * <p>Typically implementations of <code>Format</code>
-     *    ignore invalid characters at the end of the value
-     *    and just stop parsing. For example parsing a date
-     *    value of <code>01/01/20x0</code> using a pattern
-     *    of <code>dd/MM/yyyy</code> will result in a year
-     *    of <code>20</code> if <code>strict</code> is set
-     *    to <code>false</code>, whereas setting <code>strict</code>
-     *    to <code>true</code> will cause this value to fail
-     *    validation.</p>
-     *
-     * @return <code>true</code> if strict <code>Format</code>
-     *         parsing should be used.
-     */
-    public boolean isStrict() {
-        return strict;
-    }
-
-    /**
-     * <p>Validate using the default <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return <code>true</code> if the value is valid.
-     */
-    public boolean isValid(final String value) {
-        return isValid(value, (String)null, (Locale)null);
-    }
-
-    /**
-     * <p>Validate using the specified <i>pattern</i>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @return <code>true</code> if the value is valid.
-     */
-    public boolean isValid(final String value, final String pattern) {
-        return isValid(value, pattern, (Locale)null);
-    }
-
-    /**
-     * <p>Validate using the specified <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the Format, defaults to the default
-     * @return <code>true</code> if the value is valid.
-     */
-    public boolean isValid(final String value, final Locale locale) {
-        return isValid(value, (String)null, locale);
-    }
-
-    /**
-     * <p>Validate using the specified pattern and/or <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to format the value.
-     * @param locale The locale to use for the Format, defaults to the default
-     * @return <code>true</code> if the value is valid.
-     */
-    public abstract boolean isValid(String value, String pattern, Locale locale);
-
-    /**
      * <p>Format an object into a <code>String</code> using
      * the default Locale.</p>
      *
@@ -120,15 +60,14 @@
     }
 
     /**
-     * <p>Format an object into a <code>String</code> using
-     * the specified pattern.</p>
+     * <p>Format a value with the specified <code>Format</code>.</p>
      *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to format the value.
-     * @return The value formatted as a <code>String</code>.
+     * @param value The value to be formatted.
+     * @param formatter The Format to use.
+     * @return The formatted value.
      */
-    public String format(final Object value, final String pattern) {
-        return format(value, pattern, (Locale)null);
+    protected String format(final Object value, final Format formatter) {
+        return formatter.format(value);
     }
 
     /**
@@ -144,6 +83,18 @@
     }
 
     /**
+     * <p>Format an object into a <code>String</code> using
+     * the specified pattern.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to format the value.
+     * @return The value formatted as a <code>String</code>.
+     */
+    public String format(final Object value, final String pattern) {
+        return format(value, pattern, (Locale)null);
+    }
+
+    /**
      * <p>Format an object using the specified pattern and/or
      *    <code>Locale</code>.
      *
@@ -158,22 +109,85 @@
     }
 
     /**
-     * <p>Format a value with the specified <code>Format</code>.</p>
+     * <p>Returns a <code>Format</code> for the specified <i>pattern</i>
+     *    and/or <code>Locale</code>.</p>
      *
-     * @param value The value to be formatted.
-     * @param formatter The Format to use.
-     * @return The formatted value.
+     * @param pattern The pattern used to validate the value against or
+     *        {@code null} to use the default for the <code>Locale</code>.
+     * @param locale The locale to use for the currency format, system default if null.
+     * @return The <code>NumberFormat</code> to created.
      */
-    protected String format(final Object value, final Format formatter) {
-        return formatter.format(value);
+    protected abstract Format getFormat(String pattern, Locale locale);
+
+    /**
+     * <p>Indicates whether validated values should adhere
+     *    strictly to the <code>Format</code> used.</p>
+     *
+     * <p>Typically implementations of <code>Format</code>
+     *    ignore invalid characters at the end of the value
+     *    and just stop parsing. For example parsing a date
+     *    value of <code>01/01/20x0</code> using a pattern
+     *    of <code>dd/MM/yyyy</code> will result in a year
+     *    of <code>20</code> if <code>strict</code> is set
+     *    to {@code false}, whereas setting <code>strict</code>
+     *    to {@code true} will cause this value to fail
+     *    validation.</p>
+     *
+     * @return {@code true} if strict <code>Format</code>
+     *         parsing should be used.
+     */
+    public boolean isStrict() {
+        return strict;
     }
 
     /**
+     * <p>Validate using the default <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return {@code true} if the value is valid.
+     */
+    public boolean isValid(final String value) {
+        return isValid(value, (String)null, (Locale)null);
+    }
+
+    /**
+     * <p>Validate using the specified <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the Format, defaults to the default
+     * @return {@code true} if the value is valid.
+     */
+    public boolean isValid(final String value, final Locale locale) {
+        return isValid(value, (String)null, locale);
+    }
+
+    /**
+     * <p>Validate using the specified <i>pattern</i>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @return {@code true} if the value is valid.
+     */
+    public boolean isValid(final String value, final String pattern) {
+        return isValid(value, pattern, (Locale)null);
+    }
+
+    /**
+     * <p>Validate using the specified pattern and/or <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to format the value.
+     * @param locale The locale to use for the Format, defaults to the default
+     * @return {@code true} if the value is valid.
+     */
+    public abstract boolean isValid(String value, String pattern, Locale locale);
+
+    /**
      * <p>Parse the value with the specified <code>Format</code>.</p>
      *
      * @param value The value to be parsed.
      * @param formatter The Format to parse the value with.
-     * @return The parsed value if valid or <code>null</code> if invalid.
+     * @return The parsed value if valid or {@code null} if invalid.
      */
     protected Object parse(final String value, final Format formatter) {
 
@@ -202,19 +216,8 @@
      * @param value The parsed object created.
      * @param formatter The Format used to parse the value with.
      * @return The parsed value converted to the appropriate type
-     *         if valid or <code>null</code> if invalid.
+     *         if valid or {@code null} if invalid.
      */
     protected abstract Object processParsedValue(Object value, Format formatter);
 
-    /**
-     * <p>Returns a <code>Format</code> for the specified <i>pattern</i>
-     *    and/or <code>Locale</code>.</p>
-     *
-     * @param pattern The pattern used to validate the value against or
-     *        <code>null</code> to use the default for the <code>Locale</code>.
-     * @param locale The locale to use for the currency format, system default if null.
-     * @return The <code>NumberFormat</code> to created.
-     */
-    protected abstract Format getFormat(String pattern, Locale locale);
-
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/AbstractNumberValidator.java b/src/main/java/org/apache/commons/validator/routines/AbstractNumberValidator.java
index 61ecdf5..e2dc0f1 100644
--- a/src/main/java/org/apache/commons/validator/routines/AbstractNumberValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/AbstractNumberValidator.java
@@ -41,21 +41,28 @@
     public static final int CURRENCY_FORMAT = 1;
 
     /** Percent <code>NumberFormat</code> type */
-    public static final int PERCENT_FORMAT  = 2;
-
-    private final boolean allowFractions;
-    private final int     formatType;
+    public static final int PERCENT_FORMAT = 2;
 
     /**
-     * Construct an instance with specified <i>strict</i>
+     * {@code true} if fractions are allowed or {@code false} if integers only.
+     */
+    private final boolean allowFractions;
+
+    /**
+     * The <code>NumberFormat</code> type to create for validation, default is STANDARD_FORMAT.
+     */
+    private final int formatType;
+
+    /**
+     * Constructs an instance with specified <i>strict</i>
      * and <i>decimal</i> parameters.
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param formatType The <code>NumberFormat</code> type to
      *        create for validation, default is STANDARD_FORMAT.
-     * @param allowFractions <code>true</code> if fractions are
-     *        allowed or <code>false</code> if integers only.
+     * @param allowFractions {@code true} if fractions are
+     *        allowed or {@code false} if integers only.
      */
     public AbstractNumberValidator(final boolean strict, final int formatType, final boolean allowFractions) {
         super(strict);
@@ -64,146 +71,6 @@
     }
 
     /**
-     * <p>Indicates whether the number being validated is
-     *    a decimal or integer.</p>
-     *
-     * @return <code>true</code> if decimals are allowed
-     *       or <code>false</code> if the number is an integer.
-     */
-    public boolean isAllowFractions() {
-        return allowFractions;
-    }
-
-    /**
-     * <p>Indicates the type of <code>NumberFormat</code> created
-     *    by this validator instance.</p>
-     *
-     * @return the format type created.
-     */
-    public int getFormatType() {
-        return formatType;
-    }
-
-    /**
-     * <p>Validate using the specified <code>Locale</code>.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return <code>true</code> if the value is valid.
-     */
-    @Override
-    public boolean isValid(final String value, final String pattern, final Locale locale) {
-        final Object parsedValue = parse(value, pattern, locale);
-        return (parsedValue == null ? false : true);
-    }
-
-    /**
-     * Check if the value is within a specified range.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value of the range.
-     * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
-     *         specified range.
-     */
-    public boolean isInRange(final Number value, final Number min, final Number max) {
-        return (minValue(value, min) && maxValue(value, max));
-    }
-
-    /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final Number value, final Number min) {
-        if (isAllowFractions()) {
-            return (value.doubleValue() >= min.doubleValue());
-        }
-        return (value.longValue() >= min.longValue());
-    }
-
-    /**
-     * Check if the value is less than or equal to a maximum.
-     *
-     * @param value The value validation is being performed on.
-     * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
-     *         or equal to the maximum.
-     */
-    public boolean maxValue(final Number value, final Number max) {
-        if (isAllowFractions()) {
-            return (value.doubleValue() <= max.doubleValue());
-        }
-        return (value.longValue() <= max.longValue());
-    }
-
-    /**
-     * <p>Parse the value using the specified pattern.</p>
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed value if valid or <code>null</code> if invalid.
-     */
-    protected Object parse(String value, final String pattern, final Locale locale) {
-
-        value = (value == null ? null : value.trim());
-        if (value == null || value.isEmpty()) {
-            return null;
-        }
-        final Format formatter = getFormat(pattern, locale);
-        return parse(value, formatter);
-
-    }
-
-    /**
-     * <p>Process the parsed value, performing any further validation
-     *    and type conversion required.</p>
-     *
-     * @param value The parsed object created.
-     * @param formatter The Format used to parse the value with.
-     * @return The parsed value converted to the appropriate type
-     *         if valid or <code>null</code> if invalid.
-     */
-    @Override
-    protected abstract Object processParsedValue(Object value, Format formatter);
-
-    /**
-     * <p>Returns a <code>NumberFormat</code> for the specified <i>pattern</i>
-     *    and/or <code>Locale</code>.</p>
-     *
-     * @param pattern The pattern used to validate the value against or
-     *        <code>null</code> to use the default for the <code>Locale</code>.
-     * @param locale The locale to use for the currency format, system default if null.
-     * @return The <code>NumberFormat</code> to created.
-     */
-    @Override
-    protected Format getFormat(final String pattern, final Locale locale) {
-
-        NumberFormat formatter;
-        final boolean usePattern = pattern != null && !pattern.isEmpty();
-        if (!usePattern) {
-            formatter = (NumberFormat)getFormat(locale);
-        } else if (locale == null) {
-            formatter =  new DecimalFormat(pattern);
-        } else {
-            final DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale);
-            formatter = new DecimalFormat(pattern, symbols);
-        }
-
-        if (!isAllowFractions()) {
-            formatter.setParseIntegerOnly(true);
-        }
-        return formatter;
-    }
-
-    /**
      * <p>Returns the <i>multiplier</i> of the <code>NumberFormat</code>.</p>
      *
      * @param format The <code>NumberFormat</code> to determine the
@@ -224,7 +91,7 @@
         }
         int scale = minimumFraction;
         if (format instanceof DecimalFormat) {
-            final int multiplier = ((DecimalFormat)format).getMultiplier();
+            final int multiplier = ((DecimalFormat) format).getMultiplier();
             if (multiplier == 100) { // CHECKSTYLE IGNORE MagicNumber
                 scale += 2; // CHECKSTYLE IGNORE MagicNumber
             } else if (multiplier == 1000) { // CHECKSTYLE IGNORE MagicNumber
@@ -273,4 +140,143 @@
         }
         return formatter;
     }
+
+    /**
+     * <p>Returns a <code>NumberFormat</code> for the specified <i>pattern</i>
+     *    and/or <code>Locale</code>.</p>
+     *
+     * @param pattern The pattern used to validate the value against or
+     *        {@code null} to use the default for the <code>Locale</code>.
+     * @param locale The locale to use for the currency format, system default if null.
+     * @return The <code>NumberFormat</code> to created.
+     */
+    @Override
+    protected Format getFormat(final String pattern, final Locale locale) {
+
+        NumberFormat formatter;
+        final boolean usePattern = pattern != null && !pattern.isEmpty();
+        if (!usePattern) {
+            formatter = (NumberFormat) getFormat(locale);
+        } else if (locale == null) {
+            formatter = new DecimalFormat(pattern);
+        } else {
+            final DecimalFormatSymbols symbols = new DecimalFormatSymbols(locale);
+            formatter = new DecimalFormat(pattern, symbols);
+        }
+
+        if (!isAllowFractions()) {
+            formatter.setParseIntegerOnly(true);
+        }
+        return formatter;
+    }
+
+    /**
+     * <p>Indicates the type of <code>NumberFormat</code> created
+     *    by this validator instance.</p>
+     *
+     * @return the format type created.
+     */
+    public int getFormatType() {
+        return formatType;
+    }
+
+    /**
+     * <p>Indicates whether the number being validated is
+     *    a decimal or integer.</p>
+     *
+     * @return {@code true} if decimals are allowed
+     *       or {@code false} if the number is an integer.
+     */
+    public boolean isAllowFractions() {
+        return allowFractions;
+    }
+
+    /**
+     * Check if the value is within a specified range.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value of the range.
+     * @param max The maximum value of the range.
+     * @return {@code true} if the value is within the
+     *         specified range.
+     */
+    public boolean isInRange(final Number value, final Number min, final Number max) {
+        return minValue(value, min) && maxValue(value, max);
+    }
+
+    /**
+     * <p>Validate using the specified <code>Locale</code>.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return {@code true} if the value is valid.
+     */
+    @Override
+    public boolean isValid(final String value, final String pattern, final Locale locale) {
+        final Object parsedValue = parse(value, pattern, locale);
+        return parsedValue == null ? false : true;
+    }
+
+    /**
+     * Check if the value is less than or equal to a maximum.
+     *
+     * @param value The value validation is being performed on.
+     * @param max The maximum value.
+     * @return {@code true} if the value is less than
+     *         or equal to the maximum.
+     */
+    public boolean maxValue(final Number value, final Number max) {
+        if (isAllowFractions()) {
+            return value.doubleValue() <= max.doubleValue();
+        }
+        return value.longValue() <= max.longValue();
+    }
+
+    /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final Number value, final Number min) {
+        if (isAllowFractions()) {
+            return value.doubleValue() >= min.doubleValue();
+        }
+        return value.longValue() >= min.longValue();
+    }
+
+    /**
+     * <p>Parse the value using the specified pattern.</p>
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed value if valid or {@code null} if invalid.
+     */
+    protected Object parse(String value, final String pattern, final Locale locale) {
+        value = value == null ? null : value.trim();
+        if (value == null || value.isEmpty()) {
+            return null;
+        }
+        final Format formatter = getFormat(pattern, locale);
+        return parse(value, formatter);
+
+    }
+
+    /**
+     * <p>Process the parsed value, performing any further validation
+     *    and type conversion required.</p>
+     *
+     * @param value The parsed object created.
+     * @param formatter The Format used to parse the value with.
+     * @return The parsed value converted to the appropriate type
+     *         if valid or {@code null} if invalid.
+     */
+    @Override
+    protected abstract Object processParsedValue(Object value, Format formatter);
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/BigDecimalValidator.java b/src/main/java/org/apache/commons/validator/routines/BigDecimalValidator.java
index 7401f1e..9a1db63 100644
--- a/src/main/java/org/apache/commons/validator/routines/BigDecimalValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/BigDecimalValidator.java
@@ -72,7 +72,7 @@
     private static final BigDecimalValidator VALIDATOR = new BigDecimalValidator();
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the BigDecimalValidator.
      */
     public static BigDecimalValidator getInstance() {
@@ -80,7 +80,7 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance.
+     * Constructs a <i>strict</i> instance.
      */
     public BigDecimalValidator() {
         this(true);
@@ -89,7 +89,7 @@
     /**
      * <p>Construct an instance with the specified strict setting.</p>
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      */
     public BigDecimalValidator(final boolean strict) {
@@ -112,12 +112,12 @@
      *           <i>percent</i> number formats (the default).</li>
      *    </ul>
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param formatType The <code>NumberFormat</code> type to
      *        create for validation, default is STANDARD_FORMAT.
-     * @param allowFractions <code>true</code> if fractions are
-     *        allowed or <code>false</code> if integers only.
+     * @param allowFractions {@code true} if fractions are
+     *        allowed or {@code false} if integers only.
      */
     protected BigDecimalValidator(final boolean strict, final int formatType,
             final boolean allowFractions) {
@@ -125,79 +125,16 @@
     }
 
     /**
-     * <p>Validate/convert a <code>BigDecimal</code> using the default
-     *    <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return The parsed <code>BigDecimal</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public BigDecimal validate(final String value) {
-        return (BigDecimal)parse(value, (String)null, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>BigDecimal</code> using the
-     *    specified <i>pattern</i>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
-     */
-    public BigDecimal validate(final String value, final String pattern) {
-        return (BigDecimal)parse(value, pattern, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>BigDecimal</code> using the
-     *    specified <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the number format, system default if null.
-     * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
-     */
-    public BigDecimal validate(final String value, final Locale locale) {
-        return (BigDecimal)parse(value, (String)null, locale);
-    }
-
-    /**
-     * <p>Validate/convert a <code>BigDecimal</code> using the
-     *    specified pattern and/ or <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
-     */
-    public BigDecimal validate(final String value, final String pattern, final Locale locale) {
-        return (BigDecimal)parse(value, pattern, locale);
-    }
-
-    /**
      * Check if the value is within a specified range.
      *
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final BigDecimal value, final double min, final double max) {
-        return (value.doubleValue() >= min && value.doubleValue() <= max);
-    }
-
-    /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final BigDecimal value, final double min) {
-        return (value.doubleValue() >= min);
+        return value.doubleValue() >= min && value.doubleValue() <= max;
     }
 
     /**
@@ -205,11 +142,23 @@
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final BigDecimal value, final double max) {
-        return (value.doubleValue() <= max);
+        return value.doubleValue() <= max;
+    }
+
+    /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final BigDecimal value, final double min) {
+        return value.doubleValue() >= min;
     }
 
     /**
@@ -236,4 +185,55 @@
 
         return decimal;
     }
+
+    /**
+     * <p>Validate/convert a <code>BigDecimal</code> using the default
+     *    <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return The parsed <code>BigDecimal</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public BigDecimal validate(final String value) {
+        return (BigDecimal)parse(value, (String)null, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>BigDecimal</code> using the
+     *    specified <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the number format, system default if null.
+     * @return The parsed <code>BigDecimal</code> if valid or {@code null} if invalid.
+     */
+    public BigDecimal validate(final String value, final Locale locale) {
+        return (BigDecimal)parse(value, (String)null, locale);
+    }
+
+    /**
+     * <p>Validate/convert a <code>BigDecimal</code> using the
+     *    specified <i>pattern</i>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @return The parsed <code>BigDecimal</code> if valid or {@code null} if invalid.
+     */
+    public BigDecimal validate(final String value, final String pattern) {
+        return (BigDecimal)parse(value, pattern, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>BigDecimal</code> using the
+     *    specified pattern and/ or <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>BigDecimal</code> if valid or {@code null} if invalid.
+     */
+    public BigDecimal validate(final String value, final String pattern, final Locale locale) {
+        return (BigDecimal)parse(value, pattern, locale);
+    }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/BigIntegerValidator.java b/src/main/java/org/apache/commons/validator/routines/BigIntegerValidator.java
index 6f9bd10..7a2d308 100644
--- a/src/main/java/org/apache/commons/validator/routines/BigIntegerValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/BigIntegerValidator.java
@@ -69,7 +69,7 @@
     private static final BigIntegerValidator VALIDATOR = new BigIntegerValidator();
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the BigIntegerValidator.
      */
     public static BigIntegerValidator getInstance() {
@@ -77,7 +77,7 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance.
+     * Constructs a <i>strict</i> instance.
      */
     public BigIntegerValidator() {
         this(true, STANDARD_FORMAT);
@@ -99,7 +99,7 @@
      *           <i>percent</i> number formats (the default).</li>
      *    </ul>
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param formatType The <code>NumberFormat</code> type to
      *        create for validation, default is STANDARD_FORMAT.
@@ -109,78 +109,16 @@
     }
 
     /**
-     * <p>Validate/convert a <code>BigInteger</code> using the default
-     *    <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return The parsed <code>BigInteger</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public BigInteger validate(final String value) {
-        return (BigInteger)parse(value, (String)null, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>BigInteger</code> using the
-     *    specified <i>pattern</i>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @return The parsed <code>BigInteger</code> if valid or <code>null</code> if invalid.
-     */
-    public BigInteger validate(final String value, final String pattern) {
-        return (BigInteger)parse(value, pattern, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>BigInteger</code> using the
-     *    specified <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the number format, system default if null.
-     * @return The parsed <code>BigInteger</code> if valid or <code>null</code> if invalid.
-     */
-    public BigInteger validate(final String value, final Locale locale) {
-        return (BigInteger)parse(value, (String)null, locale);
-    }
-
-    /**
-     * <p>Validate/convert a <code>BigInteger</code> using the
-     *    specified pattern and/ or <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>BigInteger</code> if valid or <code>null</code> if invalid.
-     */
-    public BigInteger validate(final String value, final String pattern, final Locale locale) {
-        return (BigInteger)parse(value, pattern, locale);
-    }
-
-    /**
      * Check if the value is within a specified range.
      *
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final BigInteger value, final long min, final long max) {
-        return (value.longValue() >= min && value.longValue() <= max);
-    }
-
-    /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final BigInteger value, final long min) {
-        return (value.longValue() >= min);
+        return value.longValue() >= min && value.longValue() <= max;
     }
 
     /**
@@ -188,11 +126,23 @@
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final BigInteger value, final long max) {
-        return (value.longValue() <= max);
+        return value.longValue() <= max;
+    }
+
+    /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final BigInteger value, final long min) {
+        return value.longValue() >= min;
     }
 
     /**
@@ -207,4 +157,54 @@
     protected Object processParsedValue(final Object value, final Format formatter) {
         return BigInteger.valueOf(((Number)value).longValue());
     }
+
+    /**
+     * <p>Validate/convert a <code>BigInteger</code> using the default
+     *    <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return The parsed <code>BigInteger</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public BigInteger validate(final String value) {
+        return (BigInteger)parse(value, (String)null, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>BigInteger</code> using the
+     *    specified <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the number format, system default if null.
+     * @return The parsed <code>BigInteger</code> if valid or {@code null} if invalid.
+     */
+    public BigInteger validate(final String value, final Locale locale) {
+        return (BigInteger)parse(value, (String)null, locale);
+    }
+
+    /**
+     * <p>Validate/convert a <code>BigInteger</code> using the
+     *    specified <i>pattern</i>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @return The parsed <code>BigInteger</code> if valid or {@code null} if invalid.
+     */
+    public BigInteger validate(final String value, final String pattern) {
+        return (BigInteger)parse(value, pattern, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>BigInteger</code> using the
+     *    specified pattern and/ or <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>BigInteger</code> if valid or {@code null} if invalid.
+     */
+    public BigInteger validate(final String value, final String pattern, final Locale locale) {
+        return (BigInteger)parse(value, pattern, locale);
+    }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/ByteValidator.java b/src/main/java/org/apache/commons/validator/routines/ByteValidator.java
index 34a3ada..ad26fc4 100644
--- a/src/main/java/org/apache/commons/validator/routines/ByteValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/ByteValidator.java
@@ -68,7 +68,7 @@
     private static final ByteValidator VALIDATOR = new ByteValidator();
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the ByteValidator.
      */
     public static ByteValidator getInstance() {
@@ -76,7 +76,7 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance.
+     * Constructs a <i>strict</i> instance.
      */
     public ByteValidator() {
         this(true, STANDARD_FORMAT);
@@ -98,7 +98,7 @@
      *           <i>percent</i> number formats (the default).</li>
      *    </ul>
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param formatType The <code>NumberFormat</code> type to
      *        create for validation, default is STANDARD_FORMAT.
@@ -108,66 +108,16 @@
     }
 
     /**
-     * <p>Validate/convert a <code>Byte</code> using the default
-     *    <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return The parsed <code>Byte</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public Byte validate(final String value) {
-        return (Byte)parse(value, (String)null, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Byte</code> using the
-     *    specified <i>pattern</i>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @return The parsed <code>Byte</code> if valid or <code>null</code> if invalid.
-     */
-    public Byte validate(final String value, final String pattern) {
-        return (Byte)parse(value, pattern, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Byte</code> using the
-     *    specified <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the number format, system default if null.
-     * @return The parsed <code>Byte</code> if valid or <code>null</code> if invalid.
-     */
-    public Byte validate(final String value, final Locale locale) {
-        return (Byte)parse(value, (String)null, locale);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Byte</code> using the
-     *    specified pattern and/ or <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>Byte</code> if valid or <code>null</code> if invalid.
-     */
-    public Byte validate(final String value, final String pattern, final Locale locale) {
-        return (Byte)parse(value, pattern, locale);
-    }
-
-    /**
      * Check if the value is within a specified range.
      *
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final byte value, final byte min, final byte max) {
-        return (value >= min && value <= max);
+        return value >= min && value <= max;
     }
 
     /**
@@ -176,7 +126,7 @@
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final Byte value, final byte min, final byte max) {
@@ -184,39 +134,15 @@
     }
 
     /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final byte value, final byte min) {
-        return (value >= min);
-    }
-
-    /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final Byte value, final byte min) {
-        return minValue(value.byteValue(), min);
-    }
-
-    /**
      * Check if the value is less than or equal to a maximum.
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final byte value, final byte max) {
-        return (value <= max);
+        return value <= max;
     }
 
     /**
@@ -224,7 +150,7 @@
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final Byte value, final byte max) {
@@ -232,13 +158,37 @@
     }
 
     /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final byte value, final byte min) {
+        return value >= min;
+    }
+
+    /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final Byte value, final byte min) {
+        return minValue(value.byteValue(), min);
+    }
+
+    /**
      * <p>Perform further validation and convert the <code>Number</code> to
      * a <code>Byte</code>.</p>
      *
      * @param value The parsed <code>Number</code> object created.
      * @param formatter The Format used to parse the value with.
      * @return The parsed <code>Number</code> converted to a
-     *   <code>Byte</code> if valid or <code>null</code> if invalid.
+     *   <code>Byte</code> if valid or {@code null} if invalid.
      */
     @Override
     protected Object processParsedValue(final Object value, final Format formatter) {
@@ -254,4 +204,54 @@
         return null;
     }
 
+    /**
+     * <p>Validate/convert a <code>Byte</code> using the default
+     *    <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return The parsed <code>Byte</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public Byte validate(final String value) {
+        return (Byte)parse(value, (String)null, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Byte</code> using the
+     *    specified <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the number format, system default if null.
+     * @return The parsed <code>Byte</code> if valid or {@code null} if invalid.
+     */
+    public Byte validate(final String value, final Locale locale) {
+        return (Byte)parse(value, (String)null, locale);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Byte</code> using the
+     *    specified <i>pattern</i>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @return The parsed <code>Byte</code> if valid or {@code null} if invalid.
+     */
+    public Byte validate(final String value, final String pattern) {
+        return (Byte)parse(value, pattern, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Byte</code> using the
+     *    specified pattern and/ or <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>Byte</code> if valid or {@code null} if invalid.
+     */
+    public Byte validate(final String value, final String pattern, final Locale locale) {
+        return (Byte)parse(value, pattern, locale);
+    }
+
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/CalendarValidator.java b/src/main/java/org/apache/commons/validator/routines/CalendarValidator.java
index 1700e82..4428b7c 100644
--- a/src/main/java/org/apache/commons/validator/routines/CalendarValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/CalendarValidator.java
@@ -91,138 +91,6 @@
     private static final CalendarValidator VALIDATOR = new CalendarValidator();
 
     /**
-     * Return a singleton instance of this validator.
-     * @return A singleton instance of the CalendarValidator.
-     */
-    public static CalendarValidator getInstance() {
-        return VALIDATOR;
-    }
-
-    /**
-     * Construct a <i>strict</i> instance with <i>short</i>
-     * date style.
-     */
-    public CalendarValidator() {
-        this(true, DateFormat.SHORT);
-    }
-
-    /**
-     * Construct an instance with the specified <i>strict</i>
-     * and <i>date style</i> parameters.
-     *
-     * @param strict <code>true</code> if strict
-     *        <code>Format</code> parsing should be used.
-     * @param dateStyle the date style to use for Locale validation.
-     */
-    public CalendarValidator(final boolean strict, final int dateStyle) {
-        super(strict, dateStyle, -1);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Calendar</code> using the default
-     *    <code>Locale</code> and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public Calendar validate(final String value) {
-        return (Calendar)parse(value, (String)null, (Locale)null, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Calendar</code> using the specified
-     *    <code>TimeZone</code> and default <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param timeZone The Time Zone used to parse the date, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public Calendar validate(final String value, final TimeZone timeZone) {
-        return (Calendar)parse(value, (String)null, (Locale)null, timeZone);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Calendar</code> using the specified
-     *    <i>pattern</i> and default <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final String pattern) {
-        return (Calendar)parse(value, pattern, (Locale)null, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Calendar</code> using the specified
-     *    <i>pattern</i> and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @param timeZone The Time Zone used to parse the date, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final String pattern, final TimeZone timeZone) {
-        return (Calendar)parse(value, pattern, (Locale)null, timeZone);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Calendar</code> using the specified
-     *    <code>Locale</code> and default <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final Locale locale) {
-        return (Calendar)parse(value, (String)null, locale, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Calendar</code> using the specified
-     *    <code>Locale</code> and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the date format, system default if null.
-     * @param timeZone The Time Zone used to parse the date, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final Locale locale, final TimeZone timeZone) {
-        return (Calendar)parse(value, (String)null, locale, timeZone);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Calendar</code> using the specified pattern
-     *    and <code>Locale</code> and the default <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final String pattern, final Locale locale) {
-        return (Calendar)parse(value, pattern, locale, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Calendar</code> using the specified
-     *    pattern, and <code>Locale</code> and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @param timeZone The Time Zone used to parse the date, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final String pattern, final Locale locale, final TimeZone timeZone) {
-        return (Calendar)parse(value, pattern, locale, timeZone);
-    }
-
-    /**
      * <p>Adjusts a Calendar's value to a different TimeZone.</p>
      *
      * @param value The value to adjust.
@@ -232,10 +100,10 @@
         if (value.getTimeZone().hasSameRules(timeZone)) {
             value.setTimeZone(timeZone);
         } else {
-            final int year   = value.get(Calendar.YEAR);
-            final int month  = value.get(Calendar.MONTH);
-            final int date   = value.get(Calendar.DATE);
-            final int hour   = value.get(Calendar.HOUR_OF_DAY);
+            final int year = value.get(Calendar.YEAR);
+            final int month = value.get(Calendar.MONTH);
+            final int date = value.get(Calendar.DATE);
+            final int hour = value.get(Calendar.HOUR_OF_DAY);
             final int minute = value.get(Calendar.MINUTE);
             value.setTimeZone(timeZone);
             value.set(year, month, date, hour, minute);
@@ -243,6 +111,34 @@
     }
 
     /**
+     * Gets the singleton instance of this validator.
+     * @return A singleton instance of the CalendarValidator.
+     */
+    public static CalendarValidator getInstance() {
+        return VALIDATOR;
+    }
+
+    /**
+     * Constructs a <i>strict</i> instance with <i>short</i>
+     * date style.
+     */
+    public CalendarValidator() {
+        this(true, DateFormat.SHORT);
+    }
+
+    /**
+     * Constructs an instance with the specified <i>strict</i>
+     * and <i>date style</i> parameters.
+     *
+     * @param strict {@code true} if strict
+     *        <code>Format</code> parsing should be used.
+     * @param dateStyle the date style to use for Locale validation.
+     */
+    public CalendarValidator(final boolean strict, final int dateStyle) {
+        super(strict, dateStyle, -1);
+    }
+
+    /**
      * <p>Compare Dates (day, month and year - not time).</p>
      *
      * @param value The <code>Calendar</code> value to check.
@@ -256,19 +152,6 @@
     }
 
     /**
-     * <p>Compare Weeks (week and year).</p>
-     *
-     * @param value The <code>Calendar</code> value to check.
-     * @param compare The <code>Calendar</code> to compare the value to.
-     * @return Zero if the weeks are equal, -1 if first
-     * parameter's week is less than the seconds and +1 if the first
-     * parameter's week is greater than.
-     */
-    public int compareWeeks(final Calendar value, final Calendar compare) {
-        return compare(value, compare, Calendar.WEEK_OF_YEAR);
-    }
-
-    /**
      * <p>Compare Months (month and year).</p>
      *
      * @param value The <code>Calendar</code> value to check.
@@ -310,6 +193,19 @@
     }
 
     /**
+     * <p>Compare Weeks (week and year).</p>
+     *
+     * @param value The <code>Calendar</code> value to check.
+     * @param compare The <code>Calendar</code> to compare the value to.
+     * @return Zero if the weeks are equal, -1 if first
+     * parameter's week is less than the seconds and +1 if the first
+     * parameter's week is greater than.
+     */
+    public int compareWeeks(final Calendar value, final Calendar compare) {
+        return compare(value, compare, Calendar.WEEK_OF_YEAR);
+    }
+
+    /**
      * <p>Compare Years.</p>
      *
      * @param value The <code>Calendar</code> value to check.
@@ -334,4 +230,108 @@
         return ((DateFormat)formatter).getCalendar();
     }
 
+    /**
+     * <p>Validate/convert a <code>Calendar</code> using the default
+     *    <code>Locale</code> and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return The parsed <code>Calendar</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public Calendar validate(final String value) {
+        return (Calendar)parse(value, (String)null, (Locale)null, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Calendar</code> using the specified
+     *    <code>Locale</code> and default <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final Locale locale) {
+        return (Calendar)parse(value, (String)null, locale, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Calendar</code> using the specified
+     *    <code>Locale</code> and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the date format, system default if null.
+     * @param timeZone The Time Zone used to parse the date, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final Locale locale, final TimeZone timeZone) {
+        return (Calendar)parse(value, (String)null, locale, timeZone);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Calendar</code> using the specified
+     *    <i>pattern</i> and default <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final String pattern) {
+        return (Calendar)parse(value, pattern, (Locale)null, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Calendar</code> using the specified pattern
+     *    and <code>Locale</code> and the default <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final String pattern, final Locale locale) {
+        return (Calendar)parse(value, pattern, locale, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Calendar</code> using the specified
+     *    pattern, and <code>Locale</code> and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @param timeZone The Time Zone used to parse the date, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final String pattern, final Locale locale, final TimeZone timeZone) {
+        return (Calendar)parse(value, pattern, locale, timeZone);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Calendar</code> using the specified
+     *    <i>pattern</i> and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @param timeZone The Time Zone used to parse the date, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final String pattern, final TimeZone timeZone) {
+        return (Calendar)parse(value, pattern, (Locale)null, timeZone);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Calendar</code> using the specified
+     *    <code>TimeZone</code> and default <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param timeZone The Time Zone used to parse the date, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public Calendar validate(final String value, final TimeZone timeZone) {
+        return (Calendar)parse(value, (String)null, (Locale)null, timeZone);
+    }
+
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/CodeValidator.java b/src/main/java/org/apache/commons/validator/routines/CodeValidator.java
index 689b2b7..81dd877 100644
--- a/src/main/java/org/apache/commons/validator/routines/CodeValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/CodeValidator.java
@@ -70,13 +70,61 @@
 
     private static final long serialVersionUID = 446960910870938233L;
 
+    /** The format regular expression validator. */
     private final RegexValidator regexValidator;
+
+    /** The minimum length of the code. */
     private final int minLength;
+
+    /** The maximum length of the code. */
     private final int maxLength;
+
+    /** The check digit validation routine. */
     private final CheckDigit checkdigit;
 
     /**
-     * Construct a code validator with a specified regular
+     * Constructs a code validator with a specified regular expression,
+     * validator and {@link CheckDigit} validation.
+     *
+     * @param regexValidator The format regular expression validator
+     * @param checkdigit The check digit validation routine.
+     */
+    public CodeValidator(final RegexValidator regexValidator, final CheckDigit checkdigit) {
+        this(regexValidator, -1, -1, checkdigit);
+    }
+
+    /**
+     * Constructs a code validator with a specified regular expression,
+     * validator, length and {@link CheckDigit} validation.
+     *
+     * @param regexValidator The format regular expression validator
+     * @param length The length of the code
+     *  (sets the mimimum/maximum to the same value)
+     * @param checkdigit The check digit validation routine
+     */
+    public CodeValidator(final RegexValidator regexValidator, final int length, final CheckDigit checkdigit) {
+        this(regexValidator, length, length, checkdigit);
+    }
+
+    /**
+     * Constructs a code validator with a specified regular expression
+     * validator, minimum/maximum length and {@link CheckDigit} validation.
+     *
+     * @param regexValidator The format regular expression validator
+     * @param minLength The minimum length of the code
+     * @param maxLength The maximum length of the code
+     * @param checkdigit The check digit validation routine
+     */
+    public CodeValidator(final RegexValidator regexValidator, final int minLength, final int maxLength,
+            final CheckDigit checkdigit) {
+        this.regexValidator = regexValidator;
+        this.minLength = minLength;
+        this.maxLength = maxLength;
+        this.checkdigit = checkdigit;
+    }
+
+    /**
+     * Constructs a code validator with a specified regular
      * expression and {@link CheckDigit}.
      * The RegexValidator validator is created to be case-sensitive
      *
@@ -88,7 +136,7 @@
     }
 
     /**
-     * Construct a code validator with a specified regular
+     * Constructs a code validator with a specified regular
      * expression, length and {@link CheckDigit}.
      * The RegexValidator validator is created to be case-sensitive
      *
@@ -102,7 +150,7 @@
     }
 
     /**
-     * Construct a code validator with a specified regular
+     * Constructs a code validator with a specified regular
      * expression, minimum/maximum length and {@link CheckDigit} validation.
      * The RegexValidator validator is created to be case-sensitive
      *
@@ -124,48 +172,7 @@
     }
 
     /**
-     * Construct a code validator with a specified regular expression,
-     * validator and {@link CheckDigit} validation.
-     *
-     * @param regexValidator The format regular expression validator
-     * @param checkdigit The check digit validation routine.
-     */
-    public CodeValidator(final RegexValidator regexValidator, final CheckDigit checkdigit) {
-        this(regexValidator, -1, -1, checkdigit);
-    }
-
-    /**
-     * Construct a code validator with a specified regular expression,
-     * validator, length and {@link CheckDigit} validation.
-     *
-     * @param regexValidator The format regular expression validator
-     * @param length The length of the code
-     *  (sets the mimimum/maximum to the same value)
-     * @param checkdigit The check digit validation routine
-     */
-    public CodeValidator(final RegexValidator regexValidator, final int length, final CheckDigit checkdigit) {
-        this(regexValidator, length, length, checkdigit);
-    }
-
-    /**
-     * Construct a code validator with a specified regular expression
-     * validator, minimum/maximum length and {@link CheckDigit} validation.
-     *
-     * @param regexValidator The format regular expression validator
-     * @param minLength The minimum length of the code
-     * @param maxLength The maximum length of the code
-     * @param checkdigit The check digit validation routine
-     */
-    public CodeValidator(final RegexValidator regexValidator, final int minLength, final int maxLength,
-            final CheckDigit checkdigit) {
-        this.regexValidator = regexValidator;
-        this.minLength = minLength;
-        this.maxLength = maxLength;
-        this.checkdigit = checkdigit;
-    }
-
-    /**
-     * Return the check digit validation routine.
+     * Gets the check digit validation routine.
      * <p>
      * <b>N.B.</b> Optional, if not set no Check Digit
      * validation will be performed on the code.
@@ -177,20 +184,7 @@
     }
 
     /**
-     * Return the minimum length of the code.
-     * <p>
-     * <b>N.B.</b> Optional, if less than zero the
-     * minimum length will not be checked.
-     *
-     * @return The minimum length of the code or
-     * <code>-1</code> if the code has no minimum length
-     */
-    public int getMinLength() {
-        return minLength;
-    }
-
-    /**
-     * Return the maximum length of the code.
+     * Gets the maximum length of the code.
      * <p>
      * <b>N.B.</b> Optional, if less than zero the
      * maximum length will not be checked.
@@ -203,7 +197,20 @@
     }
 
     /**
-     * Return the <i>regular expression</i> validator.
+     * Gets the minimum length of the code.
+     * <p>
+     * <b>N.B.</b> Optional, if less than zero the
+     * minimum length will not be checked.
+     *
+     * @return The minimum length of the code or
+     * <code>-1</code> if the code has no minimum length
+     */
+    public int getMinLength() {
+        return minLength;
+    }
+
+    /**
+     * Gets the <i>regular expression</i> validator.
      * <p>
      * <b>N.B.</b> Optional, if not set no regular
      * expression validation will be performed on the code.
@@ -215,8 +222,8 @@
     }
 
     /**
-     * Validate the code returning either <code>true</code>
-     * or <code>false</code>.
+     * Validate the code returning either {@code true}
+     * or {@code false}.
      * <p>
      * This calls {@link #validate(String)} and returns false
      * if the return value is null, true otherwise.
@@ -226,23 +233,23 @@
      * change the input as part of the validation.
      *
      * @param input The code to validate
-     * @return <code>true</code> if valid, otherwise
-     * <code>false</code>
+     * @return {@code true} if valid, otherwise
+     * {@code false}
      */
     public boolean isValid(final String input) {
-        return (validate(input) != null);
+        return validate(input) != null;
     }
 
     /**
      * Validate the code returning either the valid code or
-     * <code>null</code> if invalid.
+     * {@code null} if invalid.
      * <p>
      * Note that this method trims the input
      * and if there is a {@link RegexValidator} it may also
      * change the input as part of the validation.
      *
      * @param input The code to validate
-     * @return The code if valid, otherwise <code>null</code>
+     * @return The code if valid, otherwise {@code null}
      * if invalid
      */
     public Object validate(final String input) {
@@ -265,8 +272,8 @@
         }
 
         // check the length (must be done after validate as that can change the code)
-        if ((minLength >= 0 && code.length() < minLength) ||
-            (maxLength >= 0 && code.length() > maxLength)) {
+        if (minLength >= 0 && code.length() < minLength ||
+            maxLength >= 0 && code.length() > maxLength) {
             return null;
         }
 
diff --git a/src/main/java/org/apache/commons/validator/routines/CreditCardValidator.java b/src/main/java/org/apache/commons/validator/routines/CreditCardValidator.java
index a5e3531..98868e5 100644
--- a/src/main/java/org/apache/commons/validator/routines/CreditCardValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/CreditCardValidator.java
@@ -82,12 +82,6 @@
  */
 public class CreditCardValidator implements Serializable {
 
-    private static final long serialVersionUID = 5955978921148959496L;
-
-    private static final int MIN_CC_LENGTH = 12; // minimum allowed length
-
-    private static final int MAX_CC_LENGTH = 19; // maximum allowed length
-
     /**
      * Class that represents a credit card range.
      * @since 1.6
@@ -106,7 +100,8 @@
          * The low and high parameters may be shorter than the length
          * of an IIN (currently 6 digits) in which case subsequent digits
          * are ignored and may range from 0-9.
-         * <br>
+         * </p>
+         * <p>
          * The low and high parameters may be different lengths.
          * e.g. Discover "644" and "65".
          * </p>
@@ -130,7 +125,8 @@
          * The low and high parameters may be shorter than the length
          * of an IIN (currently 6 digits) in which case subsequent digits
          * are ignored and may range from 0-9.
-         * <br>
+         * </p>
+         * <p>
          * The low and high parameters may be different lengths.
          * e.g. Discover "644" and "65".
          * </p>
@@ -147,6 +143,12 @@
         }
     }
 
+    private static final long serialVersionUID = 5955978921148959496L;
+
+    private static final int MIN_CC_LENGTH = 12; // minimum allowed length
+
+    private static final int MAX_CC_LENGTH = 19; // maximum allowed length
+
     /**
      * Option specifying that no cards are allowed.  This is useful if
      * you want only custom card types to validate so you turn off the
@@ -200,12 +202,6 @@
     @Deprecated
     public static final long MASTERCARD_PRE_OCT2016 = 1 << 6; // CHECKSTYLE IGNORE MagicNumber
 
-
-    /**
-     * The CreditCardTypes that are allowed to pass validation.
-     */
-    private final List<CodeValidator> cardTypes = new ArrayList<>();
-
     /**
      * Luhn checkdigit validator for the card numbers.
      */
@@ -213,28 +209,31 @@
 
     /**
      * American Express (Amex) Card Validator
-     * <p>
-     * 34xxxx (15) <br>
-     * 37xxxx (15) <br>
+     * <ul>
+     * <li>34xxxx (15)</li>
+     * <li>37xxxx (15)</li>
+     * </ul>
      */
     public static final CodeValidator AMEX_VALIDATOR = new CodeValidator("^(3[47]\\d{13})$", LUHN_VALIDATOR);
 
     /**
      * Diners Card Validator
-     * <p>
-     * 300xxx - 305xxx (14) <br>
-     * 3095xx (14) <br>
-     * 36xxxx (14) <br>
-     * 38xxxx (14) <br>
-     * 39xxxx (14) <br>
+     * <ul>
+     * <li>300xxx - 305xxx (14)</li>
+     * <li>3095xx (14)</li>
+     * <li>36xxxx (14)</li>
+     * <li>38xxxx (14)</li>
+     * <li>39xxxx (14)</li>
+     * </ul>
      */
     public static final CodeValidator DINERS_VALIDATOR = new CodeValidator("^(30[0-5]\\d{11}|3095\\d{10}|36\\d{12}|3[8-9]\\d{12})$", LUHN_VALIDATOR);
 
     /**
      * Discover Card regular expressions
-     * <p>
-     * 6011xx (16) <br>
-     * 644xxx - 65xxxx (16) <br>
+     * <ul>
+     * <li>6011xx (16)</li>
+     * <li>644xxx - 65xxxx (16)</li>
+     * </ul>
      */
     private static final RegexValidator DISCOVER_REGEX = new RegexValidator("^(6011\\d{12,13})$", "^(64[4-9]\\d{13})$", "^(65\\d{14})$", "^(62[2-8]\\d{13})$");
 
@@ -243,9 +242,10 @@
 
     /**
      * Mastercard regular expressions
-     * <p>
-     * 2221xx - 2720xx (16) <br>
-     * 51xxx - 55xxx (16) <br>
+     * <ul>
+     * <li>2221xx - 2720xx (16)</li>
+     * <li>51xxx - 55xxx (16)</li>
+     * </ul>
      */
     private static final RegexValidator MASTERCARD_REGEX = new RegexValidator(
             "^(5[1-5]\\d{14})$",  // 51 - 55 (pre Oct 2016)
@@ -272,18 +272,118 @@
      * Visa Card Validator
      * <p>
      * 4xxxxx (13 or 16)
+     * </p>
      */
     public static final CodeValidator VISA_VALIDATOR = new CodeValidator("^(4)(\\d{12}|\\d{15})$", LUHN_VALIDATOR);
 
-    /** VPay (Visa) Card Validator
+    /**
+     * VPay (Visa) Card Validator
      * <p>
      * 4xxxxx (13-19)
+     * </p>
      * @since 1.5.0
      */
     public static final CodeValidator VPAY_VALIDATOR = new CodeValidator("^(4)(\\d{12,18})$", LUHN_VALIDATOR);
 
+    // package protected for unit test access
+    static CodeValidator createRangeValidator(final CreditCardRange[] creditCardRanges, final CheckDigit digitCheck) {
+        return new CodeValidator(
+                // must be numeric (rest of validation is done later)
+                new RegexValidator("(\\d+)") {
+                    private static final long serialVersionUID = 1L;
+                    private final transient CreditCardRange[] ccr = creditCardRanges.clone();
+
+                    @Override
+                    public boolean isValid(final String value) {
+                        return validate(value) != null;
+                    }
+
+                    @Override
+                    public String[] match(final String value) {
+                        return new String[] { validate(value) };
+                    }
+
+                    @Override
+                    // must return full string
+                    public String validate(final String value) {
+                        if (super.match(value) != null) {
+                            final int length = value.length();
+                            for (final CreditCardRange range : ccr) {
+                                if (validLength(length, range)) {
+                                    if (range.high == null) { // single prefix only
+                                        if (value.startsWith(range.low)) {
+                                            return value;
+                                        }
+                                    } else if (range.low.compareTo(value) <= 0 // no need to trim value here
+                                            &&
+                                    // here we have to ignore digits beyond the prefix
+                                            range.high.compareTo(value.substring(0, range.high.length())) >= 0) {
+                                        return value;
+                                    }
+                                }
+                            }
+                        }
+                        return null;
+                    }
+                }, digitCheck);
+    }
+
     /**
-     * Create a new CreditCardValidator with default options.
+     * Creates a new generic CreditCardValidator which validates the syntax and check digit only.
+     * Does not check the Issuer Identification Number (IIN)
+     *
+     * @return the validator
+     * @since 1.6
+     */
+    public static CreditCardValidator genericCreditCardValidator() {
+        return genericCreditCardValidator(MIN_CC_LENGTH, MAX_CC_LENGTH);
+    }
+
+    /**
+     * Creates a new generic CreditCardValidator which validates the syntax and check digit only.
+     * Does not check the Issuer Identification Number (IIN)
+     *
+     * @param length exact length
+     * @return the validator
+     * @since 1.6
+     */
+    public static CreditCardValidator genericCreditCardValidator(final int length) {
+        return genericCreditCardValidator(length, length);
+    }
+
+    /**
+     * Creates a new generic CreditCardValidator which validates the syntax and check digit only.
+     * Does not check the Issuer Identification Number (IIN)
+     *
+     * @param minLen minimum allowed length
+     * @param maxLen maximum allowed length
+     * @return the validator
+     * @since 1.6
+     */
+    public static CreditCardValidator genericCreditCardValidator(final int minLen, final int maxLen) {
+        return new CreditCardValidator(new CodeValidator[] {new CodeValidator("(\\d+)", minLen, maxLen, LUHN_VALIDATOR)});
+    }
+
+    // package protected for unit test access
+    static boolean validLength(final int valueLength, final CreditCardRange range) {
+        if (range.lengths != null) {
+            for (final int length : range.lengths) {
+                if (valueLength == length) {
+                    return true;
+                }
+            }
+            return false;
+        }
+        return valueLength >= range.minLen && valueLength <= range.maxLen;
+    }
+
+    /**
+     * The CreditCardTypes that are allowed to pass validation.
+     */
+    private final List<CodeValidator> cardTypes = new ArrayList<>();
+
+    /**
+     * Constructs a new CreditCardValidator with default options.
      * The default options are:
      * AMEX, VISA, MASTERCARD and DISCOVER
      */
@@ -292,7 +392,51 @@
     }
 
     /**
-     * Create a new CreditCardValidator with the specified options.
+     * Constructs a new CreditCardValidator with the specified {@link CodeValidator}s.
+     * @param creditCardValidators Set of valid code validators
+     */
+    public CreditCardValidator(final CodeValidator[] creditCardValidators) {
+        if (creditCardValidators == null) {
+            throw new IllegalArgumentException("Card validators are missing");
+        }
+        Collections.addAll(cardTypes, creditCardValidators);
+    }
+
+    /**
+     * Constructs a new CreditCardValidator with the specified {@link CodeValidator}s
+     * and {@link CreditCardRange}s.
+     * <p>
+     * This can be used to combine predefined validators such as {@link #MASTERCARD_VALIDATOR}
+     * with additional validators using the simpler {@link CreditCardRange}s.
+     * @param creditCardValidators Set of valid code validators
+     * @param creditCardRanges Set of valid code validators
+     * @since 1.6
+     */
+    public CreditCardValidator(final CodeValidator[] creditCardValidators, final CreditCardRange[] creditCardRanges) {
+        if (creditCardValidators == null) {
+            throw new IllegalArgumentException("Card validators are missing");
+        }
+        if (creditCardRanges == null) {
+            throw new IllegalArgumentException("Card ranges are missing");
+        }
+        Collections.addAll(cardTypes, creditCardValidators);
+        Collections.addAll(cardTypes, createRangeValidator(creditCardRanges, LUHN_VALIDATOR));
+    }
+
+    /**
+     * Constructs a new CreditCardValidator with the specified {@link CreditCardRange}s.
+     * @param creditCardRanges Set of valid code validators
+     * @since 1.6
+     */
+    public CreditCardValidator(final CreditCardRange[] creditCardRanges) {
+        if (creditCardRanges == null) {
+            throw new IllegalArgumentException("Card ranges are missing");
+        }
+        Collections.addAll(cardTypes, createRangeValidator(creditCardRanges, LUHN_VALIDATOR));
+    }
+
+    /**
+     * Constructs a new CreditCardValidator with the specified options.
      * @param options Pass in
      * CreditCardValidator.VISA + CreditCardValidator.AMEX to specify that
      * those are the only valid card types.
@@ -328,83 +472,16 @@
     }
 
     /**
-     * Create a new CreditCardValidator with the specified {@link CodeValidator}s.
-     * @param creditCardValidators Set of valid code validators
-     */
-    public CreditCardValidator(final CodeValidator[] creditCardValidators) {
-        if (creditCardValidators == null) {
-            throw new IllegalArgumentException("Card validators are missing");
-        }
-        Collections.addAll(cardTypes, creditCardValidators);
-    }
-
-    /**
-     * Create a new CreditCardValidator with the specified {@link CreditCardRange}s.
-     * @param creditCardRanges Set of valid code validators
-     * @since 1.6
-     */
-    public CreditCardValidator(final CreditCardRange[] creditCardRanges) {
-        if (creditCardRanges == null) {
-            throw new IllegalArgumentException("Card ranges are missing");
-        }
-        Collections.addAll(cardTypes, createRangeValidator(creditCardRanges, LUHN_VALIDATOR));
-    }
-
-    /**
-     * Create a new CreditCardValidator with the specified {@link CodeValidator}s
-     * and {@link CreditCardRange}s.
-     * <p>
-     * This can be used to combine predefined validators such as {@link #MASTERCARD_VALIDATOR}
-     * with additional validators using the simpler {@link CreditCardRange}s.
-     * @param creditCardValidators Set of valid code validators
-     * @param creditCardRanges Set of valid code validators
-     * @since 1.6
-     */
-    public CreditCardValidator(final CodeValidator[] creditCardValidators, final CreditCardRange[] creditCardRanges) {
-        if (creditCardValidators == null) {
-            throw new IllegalArgumentException("Card validators are missing");
-        }
-        if (creditCardRanges == null) {
-            throw new IllegalArgumentException("Card ranges are missing");
-        }
-        Collections.addAll(cardTypes, creditCardValidators);
-        Collections.addAll(cardTypes, createRangeValidator(creditCardRanges, LUHN_VALIDATOR));
-    }
-
-    /**
-     * Create a new generic CreditCardValidator which validates the syntax and check digit only.
-     * Does not check the Issuer Identification Number (IIN)
+     * Tests whether the given flag is on.  If the flag is not a power of 2
+     * (ie. 3) this tests whether the combination of flags is on.
      *
-     * @param minLen minimum allowed length
-     * @param maxLen maximum allowed length
-     * @return the validator
-     * @since 1.6
-     */
-    public static CreditCardValidator genericCreditCardValidator(final int minLen, final int maxLen) {
-        return new CreditCardValidator(new CodeValidator[] {new CodeValidator("(\\d+)", minLen, maxLen, LUHN_VALIDATOR)});
-    }
-
-    /**
-     * Create a new generic CreditCardValidator which validates the syntax and check digit only.
-     * Does not check the Issuer Identification Number (IIN)
+     * @param options The options specified.
+     * @param flag Flag value to check.
      *
-     * @param length exact length
-     * @return the validator
-     * @since 1.6
+     * @return whether the specified flag value is on.
      */
-    public static CreditCardValidator genericCreditCardValidator(final int length) {
-        return genericCreditCardValidator(length, length);
-    }
-
-    /**
-     * Create a new generic CreditCardValidator which validates the syntax and check digit only.
-     * Does not check the Issuer Identification Number (IIN)
-     *
-     * @return the validator
-     * @since 1.6
-     */
-    public static CreditCardValidator genericCreditCardValidator() {
-        return genericCreditCardValidator(MIN_CC_LENGTH, MAX_CC_LENGTH);
+    private boolean isOn(final long options, final long flag) {
+        return (options & flag) > 0;
     }
 
     /**
@@ -427,7 +504,7 @@
     /**
      * Checks if the field is a valid credit card number.
      * @param card The card number to validate.
-     * @return The card number if valid or <code>null</code>
+     * @return The card number if valid or {@code null}
      * if invalid.
      */
     public Object validate(final String card) {
@@ -445,70 +522,4 @@
 
     }
 
-    // package protected for unit test access
-    static boolean validLength(final int valueLength, final CreditCardRange range) {
-        if (range.lengths != null) {
-            for(final int length : range.lengths) {
-                if (valueLength == length) {
-                    return true;
-                }
-            }
-            return false;
-        }
-        return valueLength >= range.minLen && valueLength <= range.maxLen;
-    }
-
-    // package protected for unit test access
-    static CodeValidator createRangeValidator(final CreditCardRange[] creditCardRanges, final CheckDigit digitCheck ) {
-        return new CodeValidator(
-                // must be numeric (rest of validation is done later)
-                new RegexValidator("(\\d+)") {
-                    private static final long serialVersionUID = 1L;
-                    private final CreditCardRange[] ccr = creditCardRanges.clone();
-                    @Override
-                    // must return full string
-                    public String validate(final String value) {
-                        if (super.match(value) != null) {
-                            final int length = value.length();
-                            for(final CreditCardRange range : ccr) {
-                                if (validLength(length, range)) {
-                                    if (range.high == null) { // single prefix only
-                                        if (value.startsWith(range.low)) {
-                                            return value;
-                                        }
-                                    } else if (range.low.compareTo(value) <= 0 // no need to trim value here
-                                                &&
-                                                // here we have to ignore digits beyond the prefix
-                                                range.high.compareTo(value.substring(0, range.high.length())) >= 0) {
-                                               return value;
-                                    }
-                                }
-                            }
-                        }
-                        return null;
-                    }
-                    @Override
-                    public boolean isValid(final String value) {
-                        return validate(value) != null;
-                    }
-                    @Override
-                    public String[] match(final String value) {
-                        return new String[] { validate(value) };
-                    }
-                }, digitCheck);
-    }
-
-    /**
-     * Tests whether the given flag is on.  If the flag is not a power of 2
-     * (ie. 3) this tests whether the combination of flags is on.
-     *
-     * @param options The options specified.
-     * @param flag Flag value to check.
-     *
-     * @return whether the specified flag value is on.
-     */
-    private boolean isOn(final long options, final long flag) {
-        return (options & flag) > 0;
-    }
-
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/CurrencyValidator.java b/src/main/java/org/apache/commons/validator/routines/CurrencyValidator.java
index 34ba6ed..5afba19 100644
--- a/src/main/java/org/apache/commons/validator/routines/CurrencyValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/CurrencyValidator.java
@@ -51,7 +51,7 @@
     private static final char CURRENCY_SYMBOL = '\u00A4';
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the CurrencyValidator.
      */
     public static BigDecimalValidator getInstance() {
@@ -59,19 +59,19 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance.
+     * Constructs a <i>strict</i> instance.
      */
     public CurrencyValidator() {
         this(true, true);
     }
 
     /**
-     * Construct an instance with the specified strict setting.
+     * Constructs an instance with the specified strict setting.
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
-     * @param allowFractions <code>true</code> if fractions are
-     *        allowed or <code>false</code> if integers only.
+     * @param allowFractions {@code true} if fractions are
+     *        allowed or {@code false} if integers only.
      */
     public CurrencyValidator(final boolean strict, final boolean allowFractions) {
         super(strict, CURRENCY_FORMAT, allowFractions);
@@ -88,7 +88,7 @@
      *
      * @param value The value to be parsed.
      * @param formatter The Format to parse the value with.
-     * @return The parsed value if valid or <code>null</code> if invalid.
+     * @return The parsed value if valid or {@code null} if invalid.
      */
     @Override
     protected Object parse(final String value, final Format formatter) {
diff --git a/src/main/java/org/apache/commons/validator/routines/DateValidator.java b/src/main/java/org/apache/commons/validator/routines/DateValidator.java
index 6989580..ceeef15 100644
--- a/src/main/java/org/apache/commons/validator/routines/DateValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/DateValidator.java
@@ -88,7 +88,7 @@
     private static final DateValidator VALIDATOR = new DateValidator();
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the DateValidator.
      */
     public static DateValidator getInstance() {
@@ -96,7 +96,7 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance with <i>short</i>
+     * Constructs a <i>strict</i> instance with <i>short</i>
      * date style.
      */
     public DateValidator() {
@@ -104,10 +104,10 @@
     }
 
     /**
-     * Construct an instance with the specified <i>strict</i>
+     * Constructs an instance with the specified <i>strict</i>
      * and <i>date style</i> parameters.
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param dateStyle the date style to use for Locale validation.
      */
@@ -116,111 +116,6 @@
     }
 
     /**
-     * <p>Validate/convert a <code>Date</code> using the default
-     *    <code>Locale</code> and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return The parsed <code>Date</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public Date validate(final String value) {
-        return (Date)parse(value, (String)null, (Locale)null, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Date</code> using the specified
-     *    <code>TimeZone</code> and default <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param timeZone The Time Zone used to parse the date, system default if null.
-     * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
-     */
-    public Date validate(final String value, final TimeZone timeZone) {
-        return (Date)parse(value, (String)null, (Locale)null, timeZone);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Date</code> using the specified
-     *    <i>pattern</i> and default <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
-     */
-    public Date validate(final String value, final String pattern) {
-        return (Date)parse(value, pattern, (Locale)null, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Date</code> using the specified
-     *    <i>pattern</i> and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param timeZone The Time Zone used to parse the date, system default if null.
-     * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
-     */
-    public Date validate(final String value, final String pattern, final TimeZone timeZone) {
-        return (Date)parse(value, pattern, (Locale)null, timeZone);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Date</code> using the specified
-     *    <code>Locale</code> and default <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
-     */
-    public Date validate(final String value, final Locale locale) {
-        return (Date)parse(value, (String)null, locale, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Date</code> using the specified
-     *    <code>Locale</code> and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the date format, system default if null.
-     * @param timeZone The Time Zone used to parse the date, system default if null.
-     * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
-     */
-    public Date validate(final String value, final Locale locale, final TimeZone timeZone) {
-        return (Date)parse(value, (String)null, locale, timeZone);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Date</code> using the specified pattern
-     *    and <code>Locale</code> and the default <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
-     */
-    public Date validate(final String value, final String pattern, final Locale locale) {
-        return (Date)parse(value, pattern, locale, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Date</code> using the specified
-     *    pattern, and <code>Locale</code> and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @param timeZone The Time Zone used to parse the date, system default if null.
-     * @return The parsed <code>Date</code> if valid or <code>null</code> if invalid.
-     */
-    public Date validate(final String value, final String pattern, final Locale locale, final TimeZone timeZone) {
-        return (Date)parse(value, pattern, locale, timeZone);
-    }
-
-    /**
      * <p>Compare Dates (day, month and year - not time).</p>
      *
      * @param value The <code>Calendar</code> value to check.
@@ -231,28 +126,12 @@
      * date is greater than.
      */
     public int compareDates(final Date value, final Date compare, final TimeZone timeZone) {
-        final Calendar calendarValue   = getCalendar(value, timeZone);
+        final Calendar calendarValue = getCalendar(value, timeZone);
         final Calendar calendarCompare = getCalendar(compare, timeZone);
         return compare(calendarValue, calendarCompare, Calendar.DATE);
     }
 
     /**
-     * <p>Compare Weeks (week and year).</p>
-     *
-     * @param value The <code>Date</code> value to check.
-     * @param compare The <code>Date</code> to compare the value to.
-     * @param timeZone The Time Zone used to compare the dates, system default if null.
-     * @return Zero if the weeks are equal, -1 if first
-     * parameter's week is less than the seconds and +1 if the first
-     * parameter's week is greater than.
-     */
-    public int compareWeeks(final Date value, final Date compare, final TimeZone timeZone) {
-        final Calendar calendarValue   = getCalendar(value, timeZone);
-        final Calendar calendarCompare = getCalendar(compare, timeZone);
-        return compare(calendarValue, calendarCompare, Calendar.WEEK_OF_YEAR);
-    }
-
-    /**
      * <p>Compare Months (month and year).</p>
      *
      * @param value The <code>Date</code> value to check.
@@ -263,7 +142,7 @@
      * parameter's month is greater than.
      */
     public int compareMonths(final Date value, final Date compare, final TimeZone timeZone) {
-        final Calendar calendarValue   = getCalendar(value, timeZone);
+        final Calendar calendarValue = getCalendar(value, timeZone);
         final Calendar calendarCompare = getCalendar(compare, timeZone);
         return compare(calendarValue, calendarCompare, Calendar.MONTH);
     }
@@ -294,12 +173,28 @@
      * parameter's quarter is greater than.
      */
     public int compareQuarters(final Date value, final Date compare, final TimeZone timeZone, final int monthOfFirstQuarter) {
-        final Calendar calendarValue   = getCalendar(value, timeZone);
+        final Calendar calendarValue = getCalendar(value, timeZone);
         final Calendar calendarCompare = getCalendar(compare, timeZone);
         return super.compareQuarters(calendarValue, calendarCompare, monthOfFirstQuarter);
     }
 
     /**
+     * <p>Compare Weeks (week and year).</p>
+     *
+     * @param value The <code>Date</code> value to check.
+     * @param compare The <code>Date</code> to compare the value to.
+     * @param timeZone The Time Zone used to compare the dates, system default if null.
+     * @return Zero if the weeks are equal, -1 if first
+     * parameter's week is less than the seconds and +1 if the first
+     * parameter's week is greater than.
+     */
+    public int compareWeeks(final Date value, final Date compare, final TimeZone timeZone) {
+        final Calendar calendarValue = getCalendar(value, timeZone);
+        final Calendar calendarCompare = getCalendar(compare, timeZone);
+        return compare(calendarValue, calendarCompare, Calendar.WEEK_OF_YEAR);
+    }
+
+    /**
      * <p>Compare Years.</p>
      *
      * @param value The <code>Date</code> value to check.
@@ -310,24 +205,12 @@
      * parameter's year is greater than.
      */
     public int compareYears(final Date value, final Date compare, final TimeZone timeZone) {
-        final Calendar calendarValue   = getCalendar(value, timeZone);
+        final Calendar calendarValue = getCalendar(value, timeZone);
         final Calendar calendarCompare = getCalendar(compare, timeZone);
         return compare(calendarValue, calendarCompare, Calendar.YEAR);
     }
 
     /**
-     * <p>Returns the parsed <code>Date</code> unchanged.</p>
-     *
-     * @param value The parsed <code>Date</code> object created.
-     * @param formatter The Format used to parse the value with.
-     * @return The parsed value converted to a <code>Calendar</code>.
-     */
-    @Override
-    protected Object processParsedValue(final Object value, final Format formatter) {
-        return value;
-    }
-
-    /**
      * <p>Convert a <code>Date</code> to a <code>Calendar</code>.</p>
      *
      * @param value The date value to be converted.
@@ -346,4 +229,121 @@
 
     }
 
+    /**
+     * <p>Returns the parsed <code>Date</code> unchanged.</p>
+     *
+     * @param value The parsed <code>Date</code> object created.
+     * @param formatter The Format used to parse the value with.
+     * @return The parsed value converted to a <code>Calendar</code>.
+     */
+    @Override
+    protected Object processParsedValue(final Object value, final Format formatter) {
+        return value;
+    }
+
+    /**
+     * <p>Validate/convert a <code>Date</code> using the default
+     *    <code>Locale</code> and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return The parsed <code>Date</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public Date validate(final String value) {
+        return (Date)parse(value, (String)null, (Locale)null, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Date</code> using the specified
+     *    <code>Locale</code> and default <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>Date</code> if valid or {@code null} if invalid.
+     */
+    public Date validate(final String value, final Locale locale) {
+        return (Date)parse(value, (String)null, locale, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Date</code> using the specified
+     *    <code>Locale</code> and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the date format, system default if null.
+     * @param timeZone The Time Zone used to parse the date, system default if null.
+     * @return The parsed <code>Date</code> if valid or {@code null} if invalid.
+     */
+    public Date validate(final String value, final Locale locale, final TimeZone timeZone) {
+        return (Date)parse(value, (String)null, locale, timeZone);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Date</code> using the specified
+     *    <i>pattern</i> and default <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @return The parsed <code>Date</code> if valid or {@code null} if invalid.
+     */
+    public Date validate(final String value, final String pattern) {
+        return (Date)parse(value, pattern, (Locale)null, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Date</code> using the specified pattern
+     *    and <code>Locale</code> and the default <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>Date</code> if valid or {@code null} if invalid.
+     */
+    public Date validate(final String value, final String pattern, final Locale locale) {
+        return (Date)parse(value, pattern, locale, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Date</code> using the specified
+     *    pattern, and <code>Locale</code> and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @param timeZone The Time Zone used to parse the date, system default if null.
+     * @return The parsed <code>Date</code> if valid or {@code null} if invalid.
+     */
+    public Date validate(final String value, final String pattern, final Locale locale, final TimeZone timeZone) {
+        return (Date)parse(value, pattern, locale, timeZone);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Date</code> using the specified
+     *    <i>pattern</i> and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param timeZone The Time Zone used to parse the date, system default if null.
+     * @return The parsed <code>Date</code> if valid or {@code null} if invalid.
+     */
+    public Date validate(final String value, final String pattern, final TimeZone timeZone) {
+        return (Date)parse(value, pattern, (Locale)null, timeZone);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Date</code> using the specified
+     *    <code>TimeZone</code> and default <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param timeZone The Time Zone used to parse the date, system default if null.
+     * @return The parsed <code>Date</code> if valid or {@code null} if invalid.
+     */
+    public Date validate(final String value, final TimeZone timeZone) {
+        return (Date)parse(value, (String)null, (Locale)null, timeZone);
+    }
+
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/DomainValidator.java b/src/main/java/org/apache/commons/validator/routines/DomainValidator.java
index e3add0b..3b348e0 100644
--- a/src/main/java/org/apache/commons/validator/routines/DomainValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/DomainValidator.java
@@ -63,35 +63,71 @@
  */
 public class DomainValidator implements Serializable {
 
-    /** Maximum allowable length ({@value}) of a domain name */
-    private static final int MAX_DOMAIN_LENGTH = 253;
+    /**
+     * enum used by {@link DomainValidator#updateTLDOverride(ArrayType, String[])}
+     * to determine which override array to update / fetch
+     * @since 1.5.0
+     * @since 1.5.1 made public and added read-only array references
+     */
+    public enum ArrayType {
+        /** Update (or get a copy of) the GENERIC_TLDS_PLUS table containing additonal generic TLDs */
+        GENERIC_PLUS,
+        /** Update (or get a copy of) the GENERIC_TLDS_MINUS table containing deleted generic TLDs */
+        GENERIC_MINUS,
+        /** Update (or get a copy of) the COUNTRY_CODE_TLDS_PLUS table containing additonal country code TLDs */
+        COUNTRY_CODE_PLUS,
+        /** Update (or get a copy of) the COUNTRY_CODE_TLDS_MINUS table containing deleted country code TLDs */
+        COUNTRY_CODE_MINUS,
+        /** Gets a copy of the generic TLDS table */
+        GENERIC_RO,
+        /** Gets a copy of the country code table */
+        COUNTRY_CODE_RO,
+        /** Gets a copy of the infrastructure table */
+        INFRASTRUCTURE_RO,
+        /** Gets a copy of the local table */
+        LOCAL_RO,
+        /**
+         * Update (or get a copy of) the LOCAL_TLDS_PLUS table containing additional local TLDs
+         * @since 1.7
+         */
+        LOCAL_PLUS,
+        /**
+         * Update (or get a copy of) the LOCAL_TLDS_MINUS table containing deleted local TLDs
+         * @since 1.7
+         */
+        LOCAL_MINUS
+        ;
+    }
 
-    private static final String[] EMPTY_STRING_ARRAY = {};
+    private static class IDNBUGHOLDER {
+        private static final boolean IDN_TOASCII_PRESERVES_TRAILING_DOTS = keepsTrailingDot();
+        private static boolean keepsTrailingDot() {
+            final String input = "a."; // must be a valid name
+            return input.equals(IDN.toASCII(input));
+        }
+    }
 
-    private static final long serialVersionUID = -4407125112880174009L;
+    /**
+     * Used to specify overrides when creating a new class.
+     * @since 1.7
+     */
+    public static class Item {
+        final ArrayType type;
+        final String[] values;
+
+        /**
+         * Constructs a new instance.
+         * @param type ArrayType, e.g. GENERIC_PLUS, LOCAL_PLUS
+         * @param values array of TLDs. Will be lower-cased and sorted
+         */
+        public Item(final ArrayType type, final String... values) {
+            this.type = type;
+            this.values = values; // no need to copy here
+        }
+    }
 
     // Regular expression strings for hostnames (derived from RFC2396 and RFC 1123)
 
-    // RFC2396: domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
-    // Max 63 characters
-    private static final String DOMAIN_LABEL_REGEX = "\\p{Alnum}(?>[\\p{Alnum}-]{0,61}\\p{Alnum})?";
-
-    // RFC2396 toplabel = alpha | alpha *( alphanum | "-" ) alphanum
-    // Max 63 characters
-    private static final String TOP_LABEL_REGEX = "\\p{Alpha}(?>[\\p{Alnum}-]{0,61}\\p{Alnum})?";
-
-    // RFC2396 hostname = *( domainlabel "." ) toplabel [ "." ]
-    // Note that the regex currently requires both a domain label and a top level label, whereas
-    // the RFC does not. This is because the regex is used to detect if a TLD is present.
-    // If the match fails, input is checked against DOMAIN_LABEL_REGEX (hostnameRegex)
-    // RFC1123 sec 2.1 allows hostnames to start with a digit
-    private static final String DOMAIN_NAME_REGEX =
-            "^(?:" + DOMAIN_LABEL_REGEX + "\\.)+" + "(" + TOP_LABEL_REGEX + ")\\.?$";
-
-    private static final String UNEXPECTED_ENUM_VALUE = "Unexpected enum value: ";
-
-    private final boolean allowLocal;
-
     private static class LazyHolder { // IODH
 
         /**
@@ -108,306 +144,34 @@
 
     }
 
+    /** Maximum allowable length ({@value}) of a domain name */
+    private static final int MAX_DOMAIN_LENGTH = 253;
+
+    private static final String[] EMPTY_STRING_ARRAY = {};
+
+    private static final long serialVersionUID = -4407125112880174009L;
+
+    // RFC2396: domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
+    // Max 63 characters
+    private static final String DOMAIN_LABEL_REGEX = "\\p{Alnum}(?>[\\p{Alnum}-]{0,61}\\p{Alnum})?";
+
+    // RFC2396 toplabel = alpha | alpha *( alphanum | "-" ) alphanum
+    // Max 63 characters
+    private static final String TOP_LABEL_REGEX = "\\p{Alpha}(?>[\\p{Alnum}-]{0,61}\\p{Alnum})?";
+
     /**
      * The above instances must only be returned via the getInstance() methods.
      * This is to ensure that the override data arrays are properly protected.
      */
 
-    /**
-     * RegexValidator for matching domains.
-     */
-    private final RegexValidator domainRegex =
-            new RegexValidator(DOMAIN_NAME_REGEX);
-    /**
-     * RegexValidator for matching a local hostname
-     */
+    // RFC2396 hostname = *( domainlabel "." ) toplabel [ "." ]
+    // Note that the regex currently requires both a domain label and a top level label, whereas
+    // the RFC does not. This is because the regex is used to detect if a TLD is present.
+    // If the match fails, input is checked against DOMAIN_LABEL_REGEX (hostnameRegex)
     // RFC1123 sec 2.1 allows hostnames to start with a digit
-    private final RegexValidator hostnameRegex =
-            new RegexValidator(DOMAIN_LABEL_REGEX);
-
-    /**
-     * Returns the singleton instance of this validator. It
-     *  will not consider local addresses as valid.
-     * @return the singleton instance of this validator
-     */
-    public static synchronized DomainValidator getInstance() {
-        inUse = true;
-        return LazyHolder.DOMAIN_VALIDATOR;
-    }
-
-    /**
-     * Returns the singleton instance of this validator,
-     *  with local validation as required.
-     * @param allowLocal Should local addresses be considered valid?
-     * @return the singleton instance of this validator
-     */
-    public static synchronized DomainValidator getInstance(final boolean allowLocal) {
-        inUse = true;
-        if(allowLocal) {
-            return LazyHolder.DOMAIN_VALIDATOR_WITH_LOCAL;
-        }
-        return LazyHolder.DOMAIN_VALIDATOR;
-    }
-
-    /**
-     * Returns a new instance of this validator.
-     * The user can provide a list of {@link Item} entries which can
-     * be used to override the generic and country code lists.
-     * Note that any such entries override values provided by the
-     * {@link #updateTLDOverride(ArrayType, String[])} method
-     * If an entry for a particular type is not provided, then
-     * the class override (if any) is retained.
-     *
-     * @param allowLocal Should local addresses be considered valid?
-     * @param items - array of {@link Item} entries
-     * @return an instance of this validator
-     * @since 1.7
-     */
-    public static synchronized DomainValidator getInstance(final boolean allowLocal, final List<Item> items) {
-        inUse = true;
-        return new DomainValidator(allowLocal, items);
-    }
-
-    // instance variables allowing local overrides
-    final String[] myCountryCodeTLDsMinus;
-    final String[] myCountryCodeTLDsPlus;
-    final String[] myGenericTLDsPlus;
-    final String[] myGenericTLDsMinus;
-    final String[] myLocalTLDsPlus;
-    final String[] myLocalTLDsMinus;
-    /*
-     * N.B. It is vital that instances are immutable.
-     * This is because the default instances are shared.
-    */
-
-    // N.B. The constructors are deliberately private to avoid possible problems with unsafe publication.
-    // It is vital that the static override arrays are not mutable once they have been used in an instance
-    // The arrays could be copied into the instance variables, however if the static array were changed it could
-    // result in different settings for the shared default instances
-
-    /**
-     * Private constructor.
-    */
-    private DomainValidator(final boolean allowLocal) {
-        this.allowLocal = allowLocal;
-        // link to class overrides
-        myCountryCodeTLDsMinus = countryCodeTLDsMinus;
-        myCountryCodeTLDsPlus = countryCodeTLDsPlus;
-        myGenericTLDsPlus = genericTLDsPlus;
-        myGenericTLDsMinus = genericTLDsMinus;
-        myLocalTLDsPlus = localTLDsPlus;
-        myLocalTLDsMinus = localTLDsMinus;
-    }
-
-    /**
-     * Private constructor, allowing local overrides
-     * @since 1.7
-    */
-    private DomainValidator(final boolean allowLocal,  final List<Item> items) {
-        this.allowLocal = allowLocal;
-
-        // default to class overrides
-        String[] ccMinus = countryCodeTLDsMinus;
-        String[] ccPlus = countryCodeTLDsPlus;
-        String[] genMinus = genericTLDsMinus;
-        String[] genPlus = genericTLDsPlus;
-        String[] localMinus = localTLDsMinus;
-        String[] localPlus = localTLDsPlus;
-
-        // apply the instance overrides
-        for(final Item item: items) {
-            final String [] copy = new String[item.values.length];
-            // Comparisons are always done with lower-case entries
-            for (int i = 0; i < item.values.length; i++) {
-                copy[i] = item.values[i].toLowerCase(Locale.ENGLISH);
-            }
-            Arrays.sort(copy);
-            switch(item.type) {
-            case COUNTRY_CODE_MINUS: {
-                ccMinus = copy;
-                break;
-            }
-            case COUNTRY_CODE_PLUS: {
-                ccPlus = copy;
-                break;
-            }
-            case GENERIC_MINUS: {
-                genMinus = copy;
-                break;
-            }
-            case GENERIC_PLUS: {
-                genPlus = copy;
-                break;
-            }
-            case LOCAL_MINUS: {
-                localMinus = copy;
-                break;
-            }
-            case LOCAL_PLUS: {
-                localPlus = copy;
-                break;
-            }
-            default:
-                break;
-            }
-        }
-
-        // init the instance overrides
-        myCountryCodeTLDsMinus = ccMinus;
-        myCountryCodeTLDsPlus = ccPlus;
-        myGenericTLDsMinus = genMinus;
-        myGenericTLDsPlus = genPlus;
-        myLocalTLDsMinus = localMinus;
-        myLocalTLDsPlus = localPlus;
-    }
-
-    /**
-     * Returns true if the specified <code>String</code> parses
-     * as a valid domain name with a recognized top-level domain.
-     * The parsing is case-insensitive.
-     * @param domain the parameter to check for domain name syntax
-     * @return true if the parameter is a valid domain name
-     */
-    public boolean isValid(String domain) {
-        if (domain == null) {
-            return false;
-        }
-        domain = unicodeToASCII(domain);
-        // hosts must be equally reachable via punycode and Unicode
-        // Unicode is never shorter than punycode, so check punycode
-        // if domain did not convert, then it will be caught by ASCII
-        // checks in the regexes below
-        if (domain.length() > MAX_DOMAIN_LENGTH) {
-            return false;
-        }
-        final String[] groups = domainRegex.match(domain);
-        if (groups != null && groups.length > 0) {
-            return isValidTld(groups[0]);
-        }
-        return allowLocal && hostnameRegex.isValid(domain);
-    }
-
-    // package protected for unit test access
-    // must agree with isValid() above
-    final boolean isValidDomainSyntax(String domain) {
-        if (domain == null) {
-            return false;
-        }
-        domain = unicodeToASCII(domain);
-        // hosts must be equally reachable via punycode and Unicode
-        // Unicode is never shorter than punycode, so check punycode
-        // if domain did not convert, then it will be caught by ASCII
-        // checks in the regexes below
-        if (domain.length() > MAX_DOMAIN_LENGTH) {
-            return false;
-        }
-        final String[] groups = domainRegex.match(domain);
-        return (groups != null && groups.length > 0)
-                || hostnameRegex.isValid(domain);
-    }
-
-    /**
-     * Returns true if the specified <code>String</code> matches any
-     * IANA-defined top-level domain. Leading dots are ignored if present.
-     * The search is case-insensitive.
-     * <p>
-     * If allowLocal is true, the TLD is checked using {@link #isValidLocalTld(String)}.
-     * The TLD is then checked against {@link #isValidInfrastructureTld(String)},
-     * {@link #isValidGenericTld(String)} and {@link #isValidCountryCodeTld(String)}
-     * @param tld the parameter to check for TLD status, not null
-     * @return true if the parameter is a TLD
-     */
-    public boolean isValidTld(final String tld) {
-        if(allowLocal && isValidLocalTld(tld)) {
-            return true;
-        }
-        return isValidInfrastructureTld(tld)
-                || isValidGenericTld(tld)
-                || isValidCountryCodeTld(tld);
-    }
-
-    /**
-     * Returns true if the specified <code>String</code> matches any
-     * IANA-defined infrastructure top-level domain. Leading dots are
-     * ignored if present. The search is case-insensitive.
-     * @param iTld the parameter to check for infrastructure TLD status, not null
-     * @return true if the parameter is an infrastructure TLD
-     */
-    public boolean isValidInfrastructureTld(final String iTld) {
-        final String key = chompLeadingDot(unicodeToASCII(iTld).toLowerCase(Locale.ENGLISH));
-        return arrayContains(INFRASTRUCTURE_TLDS, key);
-    }
-
-    /**
-     * Returns true if the specified <code>String</code> matches any
-     * IANA-defined generic top-level domain. Leading dots are ignored
-     * if present. The search is case-insensitive.
-     * @param gTld the parameter to check for generic TLD status, not null
-     * @return true if the parameter is a generic TLD
-     */
-    public boolean isValidGenericTld(final String gTld) {
-        final String key = chompLeadingDot(unicodeToASCII(gTld).toLowerCase(Locale.ENGLISH));
-        return (arrayContains(GENERIC_TLDS, key) || arrayContains(myGenericTLDsPlus, key))
-                && !arrayContains(myGenericTLDsMinus, key);
-    }
-
-    /**
-     * Returns true if the specified <code>String</code> matches any
-     * IANA-defined country code top-level domain. Leading dots are
-     * ignored if present. The search is case-insensitive.
-     * @param ccTld the parameter to check for country code TLD status, not null
-     * @return true if the parameter is a country code TLD
-     */
-    public boolean isValidCountryCodeTld(final String ccTld) {
-        final String key = chompLeadingDot(unicodeToASCII(ccTld).toLowerCase(Locale.ENGLISH));
-        return (arrayContains(COUNTRY_CODE_TLDS, key) || arrayContains(myCountryCodeTLDsPlus, key))
-                && !arrayContains(myCountryCodeTLDsMinus, key);
-    }
-
-    /**
-     * Returns true if the specified <code>String</code> matches any
-     * widely used "local" domains (localhost or localdomain). Leading dots are
-     * ignored if present. The search is case-insensitive.
-     * @param lTld the parameter to check for local TLD status, not null
-     * @return true if the parameter is an local TLD
-     */
-    public boolean isValidLocalTld(final String lTld) {
-        final String key = chompLeadingDot(unicodeToASCII(lTld).toLowerCase(Locale.ENGLISH));
-        return (arrayContains(LOCAL_TLDS, key) || arrayContains(myLocalTLDsPlus, key))
-                && !arrayContains(myLocalTLDsMinus, key);
-    }
-
-    /**
-     * Does this instance allow local addresses?
-     *
-     * @return true if local addresses are allowed.
-     * @since 1.7
-     */
-    public boolean isAllowLocal() {
-        return this.allowLocal;
-    }
-
-    private String chompLeadingDot(final String str) {
-        if (str.startsWith(".")) {
-            return str.substring(1);
-        }
-        return str;
-    }
-
-    // ---------------------------------------------
-    // ----- TLDs defined by IANA
-    // ----- Authoritative and comprehensive list at:
-    // ----- http://data.iana.org/TLD/tlds-alpha-by-domain.txt
-
-    // Note that the above list is in UPPER case.
-    // The code currently converts strings to lower case (as per the tables below)
-
-    // IANA also provide an HTML list at http://www.iana.org/domains/root/db
-    // Note that this contains several country code entries which are NOT in
-    // the text file. These all have the "Not assigned" in the "Sponsoring Organisation" column
-    // For example (as of 2015-01-02):
-    // .bl  country-code    Not assigned
-    // .um  country-code    Not assigned
+    private static final String DOMAIN_NAME_REGEX =
+            "^(?:" + DOMAIN_LABEL_REGEX + "\\.)+" + "(" + TOP_LABEL_REGEX + ")\\.?$";
+    private static final String UNEXPECTED_ENUM_VALUE = "Unexpected enum value: ";
 
     // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search
     private static final String[] INFRASTRUCTURE_TLDS = {
@@ -2003,10 +1767,6 @@
        "localdomain",         // Also widely used as localhost.localdomain
        "localhost",           // RFC2606 defined
     };
-
-    // Additional arrays to supplement or override the built in ones.
-    // The PLUS arrays are valid keys, the MINUS arrays are invalid keys
-
     /*
      * This field is used to detect whether the getInstance has been called.
      * After this, the method updateTLDOverride is not allowed to be called.
@@ -2014,25 +1774,26 @@
      * synchronized methods.
      */
     private static boolean inUse;
-
     /*
      * These arrays are mutable.
      * They can only be updated by the updateTLDOverride method, and readers must first get an instance
-     * using the getInstance methods which are all (now) synchronised.
-     * The only other access is via getTLDEntries which is now synchronised.
+     * using the getInstance methods which are all (now) synchronized.
+     * The only other access is via getTLDEntries which is now synchronized.
      */
     // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search
     private static String[] countryCodeTLDsPlus = EMPTY_STRING_ARRAY;
-
     // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search
     private static String[] genericTLDsPlus = EMPTY_STRING_ARRAY;
-
     // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search
     private static String[] countryCodeTLDsMinus = EMPTY_STRING_ARRAY;
-
     // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search
     private static String[] genericTLDsMinus = EMPTY_STRING_ARRAY;
 
+    // N.B. The constructors are deliberately private to avoid possible problems with unsafe publication.
+    // It is vital that the static override arrays are not mutable once they have been used in an instance
+    // The arrays could be copied into the instance variables, however if the static array were changed it could
+    // result in different settings for the shared default instances
+
     // WARNING: this array MUST be sorted, otherwise it cannot be searched reliably using binary search
     private static String[] localTLDsMinus = EMPTY_STRING_ARRAY;
 
@@ -2040,133 +1801,69 @@
     private static String[] localTLDsPlus = EMPTY_STRING_ARRAY;
 
     /**
-     * enum used by {@link DomainValidator#updateTLDOverride(ArrayType, String[])}
-     * to determine which override array to update / fetch
-     * @since 1.5.0
-     * @since 1.5.1 made public and added read-only array references
+     * Check if a sorted array contains the specified key
+     *
+     * @param sortedArray the array to search
+     * @param key the key to find
+     * @return {@code true} if the array contains the key
      */
-    public enum ArrayType {
-        /** Update (or get a copy of) the GENERIC_TLDS_PLUS table containing additonal generic TLDs */
-        GENERIC_PLUS,
-        /** Update (or get a copy of) the GENERIC_TLDS_MINUS table containing deleted generic TLDs */
-        GENERIC_MINUS,
-        /** Update (or get a copy of) the COUNTRY_CODE_TLDS_PLUS table containing additonal country code TLDs */
-        COUNTRY_CODE_PLUS,
-        /** Update (or get a copy of) the COUNTRY_CODE_TLDS_MINUS table containing deleted country code TLDs */
-        COUNTRY_CODE_MINUS,
-        /** Get a copy of the generic TLDS table */
-        GENERIC_RO,
-        /** Get a copy of the country code table */
-        COUNTRY_CODE_RO,
-        /** Get a copy of the infrastructure table */
-        INFRASTRUCTURE_RO,
-        /** Get a copy of the local table */
-        LOCAL_RO,
-        /**
-         * Update (or get a copy of) the LOCAL_TLDS_PLUS table containing additional local TLDs
-         * @since 1.7
-         */
-        LOCAL_PLUS,
-        /**
-         * Update (or get a copy of) the LOCAL_TLDS_MINUS table containing deleted local TLDs
-         * @since 1.7
-         */
-        LOCAL_MINUS
-        ;
+    private static boolean arrayContains(final String[] sortedArray, final String key) {
+        return Arrays.binarySearch(sortedArray, key) >= 0;
     }
 
     /**
-     * Used to specify overrides when creating a new class.
+     * Returns the singleton instance of this validator. It
+     *  will not consider local addresses as valid.
+     * @return the singleton instance of this validator
+     */
+    public static synchronized DomainValidator getInstance() {
+        inUse = true;
+        return LazyHolder.DOMAIN_VALIDATOR;
+    }
+
+    /**
+     * Returns the singleton instance of this validator,
+     *  with local validation as required.
+     * @param allowLocal Should local addresses be considered valid?
+     * @return the singleton instance of this validator
+     */
+    public static synchronized DomainValidator getInstance(final boolean allowLocal) {
+        inUse = true;
+        if (allowLocal) {
+            return LazyHolder.DOMAIN_VALIDATOR_WITH_LOCAL;
+        }
+        return LazyHolder.DOMAIN_VALIDATOR;
+    }
+
+    /**
+     * Returns a new instance of this validator.
+     * The user can provide a list of {@link Item} entries which can
+     * be used to override the generic and country code lists.
+     * Note that any such entries override values provided by the
+     * {@link #updateTLDOverride(ArrayType, String[])} method
+     * If an entry for a particular type is not provided, then
+     * the class override (if any) is retained.
+     *
+     * @param allowLocal Should local addresses be considered valid?
+     * @param items - array of {@link Item} entries
+     * @return an instance of this validator
      * @since 1.7
      */
-    public static class Item {
-        final ArrayType type;
-        final String[] values;
-        /**
-         *
-         * @param type ArrayType, e.g. GENERIC_PLUS, LOCAL_PLUS
-         * @param values array of TLDs. Will be lower-cased and sorted
-         */
-        public Item(final ArrayType type, final String... values) {
-            this.type = type;
-            this.values = values; // no need to copy here
-        }
+    public static synchronized DomainValidator getInstance(final boolean allowLocal, final List<Item> items) {
+        inUse = true;
+        return new DomainValidator(allowLocal, items);
     }
 
     /**
-     * Update one of the TLD override arrays.
-     * This must only be done at program startup, before any instances are accessed using getInstance.
-     * <p>
-     * For example:
-     * <p>
-     * {@code DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, "apache")}
-     * <p>
-     * To clear an override array, provide an empty array.
-     *
-     * @param table the table to update, see {@link DomainValidator.ArrayType}
-     * Must be one of the following
-     * <ul>
-     * <li>COUNTRY_CODE_MINUS</li>
-     * <li>COUNTRY_CODE_PLUS</li>
-     * <li>GENERIC_MINUS</li>
-     * <li>GENERIC_PLUS</li>
-     * <li>LOCAL_MINUS</li>
-     * <li>LOCAL_PLUS</li>
-     * </ul>
-     * @param tlds the array of TLDs, must not be null
-     * @throws IllegalStateException if the method is called after getInstance
-     * @throws IllegalArgumentException if one of the read-only tables is requested
-     * @since 1.5.0
-     */
-    public static synchronized void updateTLDOverride(final ArrayType table, final String... tlds) {
-        if (inUse) {
-            throw new IllegalStateException("Can only invoke this method before calling getInstance");
-        }
-        final String [] copy = new String[tlds.length];
-        // Comparisons are always done with lower-case entries
-        for (int i = 0; i < tlds.length; i++) {
-            copy[i] = tlds[i].toLowerCase(Locale.ENGLISH);
-        }
-        Arrays.sort(copy);
-        switch(table) {
-        case COUNTRY_CODE_MINUS:
-            countryCodeTLDsMinus = copy;
-            break;
-        case COUNTRY_CODE_PLUS:
-            countryCodeTLDsPlus = copy;
-            break;
-        case GENERIC_MINUS:
-            genericTLDsMinus = copy;
-            break;
-        case GENERIC_PLUS:
-            genericTLDsPlus = copy;
-            break;
-        case LOCAL_MINUS:
-            localTLDsMinus = copy;
-            break;
-        case LOCAL_PLUS:
-            localTLDsPlus = copy;
-            break;
-        case COUNTRY_CODE_RO:
-        case GENERIC_RO:
-        case INFRASTRUCTURE_RO:
-        case LOCAL_RO:
-            throw new IllegalArgumentException("Cannot update the table: " + table);
-        default:
-            throw new IllegalArgumentException(UNEXPECTED_ENUM_VALUE + table);
-        }
-    }
-
-    /**
-     * Get a copy of a class level internal array.
+     * Gets a copy of a class level internal array.
      * @param table the array type (any of the enum values)
      * @return a copy of the array
      * @throws IllegalArgumentException if the table type is unexpected (should not happen)
      * @since 1.5.1
      */
-    public static synchronized String [] getTLDEntries(final ArrayType table) {
+    public static synchronized String[] getTLDEntries(final ArrayType table) {
         final String[] array;
-        switch(table) {
+        switch (table) {
         case COUNTRY_CODE_MINUS:
             array = countryCodeTLDsMinus;
             break;
@@ -2203,16 +1900,275 @@
         return Arrays.copyOf(array, array.length); // clone the array
     }
 
+    /*
+     * Check if input contains only ASCII
+     * Treats null as all ASCII
+     */
+    private static boolean isOnlyASCII(final String input) {
+        if (input == null) {
+            return true;
+        }
+        for (int i = 0; i < input.length(); i++) {
+            if (input.charAt(i) > 0x7F) { // CHECKSTYLE IGNORE MagicNumber
+                return false;
+            }
+        }
+        return true;
+    }
+
     /**
-     * Get a copy of an instance level internal array.
+     * Converts potentially Unicode input to punycode.
+     * If conversion fails, returns the original input.
+     *
+     * @param input the string to convert, not null
+     * @return converted input, or original input if conversion fails
+     */
+    // Needed by UrlValidator
+    static String unicodeToASCII(final String input) {
+        if (isOnlyASCII(input)) { // skip possibly expensive processing
+            return input;
+        }
+        try {
+            final String ascii = IDN.toASCII(input);
+            if (IDNBUGHOLDER.IDN_TOASCII_PRESERVES_TRAILING_DOTS) {
+                return ascii;
+            }
+            final int length = input.length();
+            if (length == 0) { // check there is a last character
+                return input;
+            }
+            // RFC3490 3.1. 1)
+            // Whenever dots are used as label separators, the following
+            // characters MUST be recognized as dots: U+002E (full stop), U+3002
+            // (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61
+            // (halfwidth ideographic full stop).
+            final char lastChar = input.charAt(length - 1);// fetch original last char
+            switch (lastChar) {
+            case '\u002E': // "." full stop
+            case '\u3002': // ideographic full stop
+            case '\uFF0E': // fullwidth full stop
+            case '\uFF61': // halfwidth ideographic full stop
+                return ascii + "."; // restore the missing stop
+            default:
+                return ascii;
+            }
+        } catch (final IllegalArgumentException e) { // input is not valid
+            return input;
+        }
+    }
+
+    /**
+     * Update one of the TLD override arrays.
+     * This must only be done at program startup, before any instances are accessed using getInstance.
+     * <p>
+     * For example:
+     * <p>
+     * {@code DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, "apache")}
+     * <p>
+     * To clear an override array, provide an empty array.
+     *
+     * @param table the table to update, see {@link DomainValidator.ArrayType}
+     * Must be one of the following
+     * <ul>
+     * <li>COUNTRY_CODE_MINUS</li>
+     * <li>COUNTRY_CODE_PLUS</li>
+     * <li>GENERIC_MINUS</li>
+     * <li>GENERIC_PLUS</li>
+     * <li>LOCAL_MINUS</li>
+     * <li>LOCAL_PLUS</li>
+     * </ul>
+     * @param tlds the array of TLDs, must not be null
+     * @throws IllegalStateException if the method is called after getInstance
+     * @throws IllegalArgumentException if one of the read-only tables is requested
+     * @since 1.5.0
+     */
+    public static synchronized void updateTLDOverride(final ArrayType table, final String... tlds) {
+        if (inUse) {
+            throw new IllegalStateException("Can only invoke this method before calling getInstance");
+        }
+        final String[] copy = new String[tlds.length];
+        // Comparisons are always done with lower-case entries
+        for (int i = 0; i < tlds.length; i++) {
+            copy[i] = tlds[i].toLowerCase(Locale.ENGLISH);
+        }
+        Arrays.sort(copy);
+        switch (table) {
+        case COUNTRY_CODE_MINUS:
+            countryCodeTLDsMinus = copy;
+            break;
+        case COUNTRY_CODE_PLUS:
+            countryCodeTLDsPlus = copy;
+            break;
+        case GENERIC_MINUS:
+            genericTLDsMinus = copy;
+            break;
+        case GENERIC_PLUS:
+            genericTLDsPlus = copy;
+            break;
+        case LOCAL_MINUS:
+            localTLDsMinus = copy;
+            break;
+        case LOCAL_PLUS:
+            localTLDsPlus = copy;
+            break;
+        case COUNTRY_CODE_RO:
+        case GENERIC_RO:
+        case INFRASTRUCTURE_RO:
+        case LOCAL_RO:
+            throw new IllegalArgumentException("Cannot update the table: " + table);
+        default:
+            throw new IllegalArgumentException(UNEXPECTED_ENUM_VALUE + table);
+        }
+    }
+
+    /** Whether to allow local overrides. */
+    private final boolean allowLocal;
+
+    // TLDs defined by IANA
+    // Authoritative and comprehensive list at:
+    // https://data.iana.org/TLD/tlds-alpha-by-domain.txt
+
+    // Note that the above list is in UPPER case.
+    // The code currently converts strings to lower case (as per the tables below)
+
+    // IANA also provide an HTML list at http://www.iana.org/domains/root/db
+    // Note that this contains several country code entries which are NOT in
+    // the text file. These all have the "Not assigned" in the "Sponsoring Organisation" column
+    // For example (as of 2015-01-02):
+    // .bl  country-code    Not assigned
+    // .um  country-code    Not assigned
+
+    /**
+     * RegexValidator for matching domains.
+     */
+    private final RegexValidator domainRegex =
+            new RegexValidator(DOMAIN_NAME_REGEX);
+
+    /**
+     * RegexValidator for matching a local hostname
+     */
+    // RFC1123 sec 2.1 allows hostnames to start with a digit
+    private final RegexValidator hostnameRegex =
+            new RegexValidator(DOMAIN_LABEL_REGEX);
+
+    /** Local override. */
+    final String[] myCountryCodeTLDsMinus;
+
+    /** Local override. */
+    final String[] myCountryCodeTLDsPlus;
+
+    // Additional arrays to supplement or override the built in ones.
+    // The PLUS arrays are valid keys, the MINUS arrays are invalid keys
+
+    /** Local override. */
+    final String[] myGenericTLDsPlus;
+
+    /** Local override. */
+    final String[] myGenericTLDsMinus;
+
+    /** Local override. */
+    final String[] myLocalTLDsPlus;
+
+    /** Local override. */
+    final String[] myLocalTLDsMinus;
+
+    /*
+     * It is vital that instances are immutable. This is because the default instances are shared.
+     */
+
+    /**
+     * Private constructor.
+     */
+    private DomainValidator(final boolean allowLocal) {
+        this.allowLocal = allowLocal;
+        // link to class overrides
+        myCountryCodeTLDsMinus = countryCodeTLDsMinus;
+        myCountryCodeTLDsPlus = countryCodeTLDsPlus;
+        myGenericTLDsPlus = genericTLDsPlus;
+        myGenericTLDsMinus = genericTLDsMinus;
+        myLocalTLDsPlus = localTLDsPlus;
+        myLocalTLDsMinus = localTLDsMinus;
+    }
+
+    /**
+     * Private constructor, allowing local overrides
+     * @since 1.7
+    */
+    private DomainValidator(final boolean allowLocal, final List<Item> items) {
+        this.allowLocal = allowLocal;
+
+        // default to class overrides
+        String[] ccMinus = countryCodeTLDsMinus;
+        String[] ccPlus = countryCodeTLDsPlus;
+        String[] genMinus = genericTLDsMinus;
+        String[] genPlus = genericTLDsPlus;
+        String[] localMinus = localTLDsMinus;
+        String[] localPlus = localTLDsPlus;
+
+        // apply the instance overrides
+        for (final Item item : items) {
+            final String[] copy = new String[item.values.length];
+            // Comparisons are always done with lower-case entries
+            for (int i = 0; i < item.values.length; i++) {
+                copy[i] = item.values[i].toLowerCase(Locale.ENGLISH);
+            }
+            Arrays.sort(copy);
+            switch (item.type) {
+            case COUNTRY_CODE_MINUS: {
+                ccMinus = copy;
+                break;
+            }
+            case COUNTRY_CODE_PLUS: {
+                ccPlus = copy;
+                break;
+            }
+            case GENERIC_MINUS: {
+                genMinus = copy;
+                break;
+            }
+            case GENERIC_PLUS: {
+                genPlus = copy;
+                break;
+            }
+            case LOCAL_MINUS: {
+                localMinus = copy;
+                break;
+            }
+            case LOCAL_PLUS: {
+                localPlus = copy;
+                break;
+            }
+            default:
+                break;
+            }
+        }
+
+        // init the instance overrides
+        myCountryCodeTLDsMinus = ccMinus;
+        myCountryCodeTLDsPlus = ccPlus;
+        myGenericTLDsMinus = genMinus;
+        myGenericTLDsPlus = genPlus;
+        myLocalTLDsMinus = localMinus;
+        myLocalTLDsPlus = localPlus;
+    }
+
+    private String chompLeadingDot(final String str) {
+        if (str.startsWith(".")) {
+            return str.substring(1);
+        }
+        return str;
+    }
+
+    /**
+     * Gets a copy of an instance level internal array.
      * @param table the array type (any of the enum values)
      * @return a copy of the array
      * @throws IllegalArgumentException if the table type is unexpected, e.g. GENERIC_RO
      * @since 1.7
      */
-    public String [] getOverrides(final ArrayType table) {
+    public String[] getOverrides(final ArrayType table) {
         final String[] array;
-        switch(table) {
+        switch (table) {
         case COUNTRY_CODE_MINUS:
             array = myCountryCodeTLDsMinus;
             break;
@@ -2236,79 +2192,126 @@
         }
         return Arrays.copyOf(array, array.length); // clone the array
     }
+
     /**
-     * Converts potentially Unicode input to punycode.
-     * If conversion fails, returns the original input.
+     * Does this instance allow local addresses?
      *
-     * @param input the string to convert, not null
-     * @return converted input, or original input if conversion fails
+     * @return true if local addresses are allowed.
+     * @since 1.7
      */
-    // Needed by UrlValidator
-    static String unicodeToASCII(final String input) {
-        if (isOnlyASCII(input)) { // skip possibly expensive processing
-            return input;
-        }
-        try {
-            final String ascii = IDN.toASCII(input);
-            if (IDNBUGHOLDER.IDN_TOASCII_PRESERVES_TRAILING_DOTS) {
-                return ascii;
-            }
-            final int length = input.length();
-            if (length == 0) {// check there is a last character
-                return input;
-            }
-            // RFC3490 3.1. 1)
-            //            Whenever dots are used as label separators, the following
-            //            characters MUST be recognized as dots: U+002E (full stop), U+3002
-            //            (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61
-            //            (halfwidth ideographic full stop).
-            final char lastChar = input.charAt(length-1);// fetch original last char
-            switch(lastChar) {
-                case '\u002E': // "." full stop
-                case '\u3002': // ideographic full stop
-                case '\uFF0E': // fullwidth full stop
-                case '\uFF61': // halfwidth ideographic full stop
-                    return ascii + "."; // restore the missing stop
-                default:
-                    return ascii;
-            }
-        } catch (final IllegalArgumentException e) { // input is not valid
-            return input;
-        }
+    public boolean isAllowLocal() {
+        return this.allowLocal;
     }
 
-    private static class IDNBUGHOLDER {
-        private static boolean keepsTrailingDot() {
-            final String input = "a."; // must be a valid name
-            return input.equals(IDN.toASCII(input));
+    /**
+     * Returns true if the specified <code>String</code> parses
+     * as a valid domain name with a recognized top-level domain.
+     * The parsing is case-insensitive.
+     * @param domain the parameter to check for domain name syntax
+     * @return true if the parameter is a valid domain name
+     */
+    public boolean isValid(String domain) {
+        if (domain == null) {
+            return false;
         }
-        private static final boolean IDN_TOASCII_PRESERVES_TRAILING_DOTS = keepsTrailingDot();
+        domain = unicodeToASCII(domain);
+        // hosts must be equally reachable via punycode and Unicode
+        // Unicode is never shorter than punycode, so check punycode
+        // if domain did not convert, then it will be caught by ASCII
+        // checks in the regexes below
+        if (domain.length() > MAX_DOMAIN_LENGTH) {
+            return false;
+        }
+        final String[] groups = domainRegex.match(domain);
+        if (groups != null && groups.length > 0) {
+            return isValidTld(groups[0]);
+        }
+        return allowLocal && hostnameRegex.isValid(domain);
     }
 
-    /*
-     * Check if input contains only ASCII
-     * Treats null as all ASCII
+    /**
+     * Returns true if the specified <code>String</code> matches any
+     * IANA-defined country code top-level domain. Leading dots are
+     * ignored if present. The search is case-insensitive.
+     * @param ccTld the parameter to check for country code TLD status, not null
+     * @return true if the parameter is a country code TLD
      */
-    private static boolean isOnlyASCII(final String input) {
-        if (input == null) {
+    public boolean isValidCountryCodeTld(final String ccTld) {
+        final String key = chompLeadingDot(unicodeToASCII(ccTld).toLowerCase(Locale.ENGLISH));
+        return (arrayContains(COUNTRY_CODE_TLDS, key) || arrayContains(myCountryCodeTLDsPlus, key)) && !arrayContains(myCountryCodeTLDsMinus, key);
+    }
+
+    // package protected for unit test access
+    // must agree with isValid() above
+    final boolean isValidDomainSyntax(String domain) {
+        if (domain == null) {
+            return false;
+        }
+        domain = unicodeToASCII(domain);
+        // hosts must be equally reachable via punycode and Unicode
+        // Unicode is never shorter than punycode, so check punycode
+        // if domain did not convert, then it will be caught by ASCII
+        // checks in the regexes below
+        if (domain.length() > MAX_DOMAIN_LENGTH) {
+            return false;
+        }
+        final String[] groups = domainRegex.match(domain);
+        return groups != null && groups.length > 0 || hostnameRegex.isValid(domain);
+    }
+    /**
+     * Returns true if the specified <code>String</code> matches any
+     * IANA-defined generic top-level domain. Leading dots are ignored
+     * if present. The search is case-insensitive.
+     * @param gTld the parameter to check for generic TLD status, not null
+     * @return true if the parameter is a generic TLD
+     */
+    public boolean isValidGenericTld(final String gTld) {
+        final String key = chompLeadingDot(unicodeToASCII(gTld).toLowerCase(Locale.ENGLISH));
+        return (arrayContains(GENERIC_TLDS, key) || arrayContains(myGenericTLDsPlus, key)) && !arrayContains(myGenericTLDsMinus, key);
+    }
+
+    /**
+     * Returns true if the specified <code>String</code> matches any
+     * IANA-defined infrastructure top-level domain. Leading dots are
+     * ignored if present. The search is case-insensitive.
+     * @param iTld the parameter to check for infrastructure TLD status, not null
+     * @return true if the parameter is an infrastructure TLD
+     */
+    public boolean isValidInfrastructureTld(final String iTld) {
+        final String key = chompLeadingDot(unicodeToASCII(iTld).toLowerCase(Locale.ENGLISH));
+        return arrayContains(INFRASTRUCTURE_TLDS, key);
+    }
+
+    /**
+     * Returns true if the specified <code>String</code> matches any
+     * widely used "local" domains (localhost or localdomain). Leading dots are
+     * ignored if present. The search is case-insensitive.
+     * @param lTld the parameter to check for local TLD status, not null
+     * @return true if the parameter is an local TLD
+     */
+    public boolean isValidLocalTld(final String lTld) {
+        final String key = chompLeadingDot(unicodeToASCII(lTld).toLowerCase(Locale.ENGLISH));
+        return (arrayContains(LOCAL_TLDS, key) || arrayContains(myLocalTLDsPlus, key))
+                && !arrayContains(myLocalTLDsMinus, key);
+    }
+
+    /**
+     * Returns true if the specified <code>String</code> matches any
+     * IANA-defined top-level domain. Leading dots are ignored if present.
+     * The search is case-insensitive.
+     * <p>
+     * If allowLocal is true, the TLD is checked using {@link #isValidLocalTld(String)}.
+     * The TLD is then checked against {@link #isValidInfrastructureTld(String)},
+     * {@link #isValidGenericTld(String)} and {@link #isValidCountryCodeTld(String)}
+     * @param tld the parameter to check for TLD status, not null
+     * @return true if the parameter is a TLD
+     */
+    public boolean isValidTld(final String tld) {
+        if (allowLocal && isValidLocalTld(tld)) {
             return true;
         }
-        for(int i=0; i < input.length(); i++) {
-            if (input.charAt(i) > 0x7F) { // CHECKSTYLE IGNORE MagicNumber
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Check if a sorted array contains the specified key
-     *
-     * @param sortedArray the array to search
-     * @param key the key to find
-     * @return {@code true} if the array contains the key
-     */
-    private static boolean arrayContains(final String[] sortedArray, final String key) {
-        return Arrays.binarySearch(sortedArray, key) >= 0;
+        return isValidInfrastructureTld(tld)
+                || isValidGenericTld(tld)
+                || isValidCountryCodeTld(tld);
     }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/DoubleValidator.java b/src/main/java/org/apache/commons/validator/routines/DoubleValidator.java
index e3cbd48..f7ef52e 100644
--- a/src/main/java/org/apache/commons/validator/routines/DoubleValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/DoubleValidator.java
@@ -68,7 +68,7 @@
     private static final DoubleValidator VALIDATOR = new DoubleValidator();
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the DoubleValidator.
      */
     public static DoubleValidator getInstance() {
@@ -76,7 +76,7 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance.
+     * Constructs a <i>strict</i> instance.
      */
     public DoubleValidator() {
         this(true, STANDARD_FORMAT);
@@ -98,7 +98,7 @@
      *           <i>percent</i> number formats (the default).</li>
      *    </ul>
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param formatType The <code>NumberFormat</code> type to
      *        create for validation, default is STANDARD_FORMAT.
@@ -108,66 +108,16 @@
     }
 
     /**
-     * <p>Validate/convert a <code>Double</code> using the default
-     *    <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return The parsed <code>Double</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public Double validate(final String value) {
-        return (Double)parse(value, (String)null, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Double</code> using the
-     *    specified <i>pattern</i>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @return The parsed <code>BigDecimal</code> if valid or <code>null</code> if invalid.
-     */
-    public Double validate(final String value, final String pattern) {
-        return (Double)parse(value, pattern, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Double</code> using the
-     *    specified <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the number format, system default if null.
-     * @return The parsed <code>Double</code> if valid or <code>null</code> if invalid.
-     */
-    public Double validate(final String value, final Locale locale) {
-        return (Double)parse(value, (String)null, locale);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Double</code> using the
-     *    specified pattern and/ or <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>Double</code> if valid or <code>null</code> if invalid.
-     */
-    public Double validate(final String value, final String pattern, final Locale locale) {
-        return (Double)parse(value, pattern, locale);
-    }
-
-    /**
      * Check if the value is within a specified range.
      *
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final double value, final double min, final double max) {
-        return (value >= min && value <= max);
+        return value >= min && value <= max;
     }
 
     /**
@@ -176,7 +126,7 @@
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final Double value, final double min, final double max) {
@@ -184,39 +134,15 @@
     }
 
     /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final double value, final double min) {
-        return (value >= min);
-    }
-
-    /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final Double value, final double min) {
-        return minValue(value.doubleValue(), min);
-    }
-
-    /**
      * Check if the value is less than or equal to a maximum.
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final double value, final double max) {
-        return (value <= max);
+        return value <= max;
     }
 
     /**
@@ -224,7 +150,7 @@
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final Double value, final double max) {
@@ -232,12 +158,36 @@
     }
 
     /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final double value, final double min) {
+        return value >= min;
+    }
+
+    /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final Double value, final double min) {
+        return minValue(value.doubleValue(), min);
+    }
+
+    /**
      * Convert the parsed value to a <code>Double</code>.
      *
      * @param value The parsed <code>Number</code> object created.
      * @param formatter The Format used to parse the value with.
      * @return The validated/converted <code>Double</code> value if valid
-     * or <code>null</code> if invalid.
+     * or {@code null} if invalid.
      */
     @Override
     protected Object processParsedValue(final Object value, final Format formatter) {
@@ -248,4 +198,54 @@
         return Double.valueOf(((Number)value).doubleValue());
 
     }
+
+    /**
+     * <p>Validate/convert a <code>Double</code> using the default
+     *    <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return The parsed <code>Double</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public Double validate(final String value) {
+        return (Double)parse(value, (String)null, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Double</code> using the
+     *    specified <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the number format, system default if null.
+     * @return The parsed <code>Double</code> if valid or {@code null} if invalid.
+     */
+    public Double validate(final String value, final Locale locale) {
+        return (Double)parse(value, (String)null, locale);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Double</code> using the
+     *    specified <i>pattern</i>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @return The parsed <code>BigDecimal</code> if valid or {@code null} if invalid.
+     */
+    public Double validate(final String value, final String pattern) {
+        return (Double)parse(value, pattern, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Double</code> using the
+     *    specified pattern and/ or <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>Double</code> if valid or {@code null} if invalid.
+     */
+    public Double validate(final String value, final String pattern, final Locale locale) {
+        return (Double)parse(value, pattern, locale);
+    }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/EmailValidator.java b/src/main/java/org/apache/commons/validator/routines/EmailValidator.java
index 14a996d..d370d08 100644
--- a/src/main/java/org/apache/commons/validator/routines/EmailValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/EmailValidator.java
@@ -24,7 +24,7 @@
  * <p>Perform email validations.</p>
  * <p>
  * Based on a script by <a href="mailto:stamhankar@hotmail.com">Sandeep V. Tamhankar</a>
- * http://javascript.internet.com
+ * https://javascript.internet.com
  * </p>
  * <p>
  * This implementation is not guaranteed to catch all possible errors in an email address.
@@ -51,8 +51,6 @@
 
     private static final int MAX_USERNAME_LEN = 64;
 
-    private final boolean allowTld;
-
     /**
      * Singleton instance of this class, which
      *  doesn't consider local addresses as valid.
@@ -71,15 +69,12 @@
      */
     private static final EmailValidator EMAIL_VALIDATOR_WITH_LOCAL = new EmailValidator(true, false);
 
-
     /**
      * Singleton instance of this class, which does
      *  consider local addresses valid.
      */
     private static final EmailValidator EMAIL_VALIDATOR_WITH_LOCAL_WITH_TLD = new EmailValidator(true, true);
 
-    private final DomainValidator domainValidator;
-
     /**
      * Returns the Singleton instance of this validator.
      *
@@ -94,6 +89,17 @@
      *  with local validation as required.
      *
      * @param allowLocal Should local addresses be considered valid?
+     * @return singleton instance of this validator
+     */
+    public static EmailValidator getInstance(final boolean allowLocal) {
+        return getInstance(allowLocal, false);
+    }
+
+    /**
+     * Returns the Singleton instance of this validator,
+     *  with local validation as required.
+     *
+     * @param allowLocal Should local addresses be considered valid?
      * @param allowTld Should TLDs be allowed?
      * @return singleton instance of this validator
      */
@@ -110,15 +116,28 @@
         return EMAIL_VALIDATOR;
     }
 
+    private final boolean allowTld;
+
+    private final DomainValidator domainValidator;
+
     /**
-     * Returns the Singleton instance of this validator,
-     *  with local validation as required.
+     * Protected constructor for subclasses to use.
      *
      * @param allowLocal Should local addresses be considered valid?
-     * @return singleton instance of this validator
      */
-    public static EmailValidator getInstance(final boolean allowLocal) {
-        return getInstance(allowLocal, false);
+    protected EmailValidator(final boolean allowLocal) {
+        this(allowLocal, false);
+    }
+
+    /**
+     * Protected constructor for subclasses to use.
+     *
+     * @param allowLocal Should local addresses be considered valid?
+     * @param allowTld Should TLDs be allowed?
+     */
+    protected EmailValidator(final boolean allowLocal, final boolean allowTld) {
+        this.allowTld = allowTld;
+        this.domainValidator = DomainValidator.getInstance(allowLocal);
     }
 
     /**
@@ -142,29 +161,9 @@
     }
 
     /**
-     * Protected constructor for subclasses to use.
-     *
-     * @param allowLocal Should local addresses be considered valid?
-     * @param allowTld Should TLDs be allowed?
-     */
-    protected EmailValidator(final boolean allowLocal, final boolean allowTld) {
-        this.allowTld = allowTld;
-        this.domainValidator = DomainValidator.getInstance(allowLocal);
-    }
-
-    /**
-     * Protected constructor for subclasses to use.
-     *
-     * @param allowLocal Should local addresses be considered valid?
-     */
-    protected EmailValidator(final boolean allowLocal) {
-        this(allowLocal, false);
-    }
-
-    /**
      * <p>Checks if a field has a valid e-mail address.</p>
      *
-     * @param email The value validation is being performed on.  A <code>null</code>
+     * @param email The value validation is being performed on.  A {@code null}
      *              value is considered invalid.
      * @return true if the email address is valid.
      */
@@ -211,7 +210,7 @@
         }
         // Domain is symbolic name
         if (allowTld) {
-            return domainValidator.isValid(domain) || (!domain.startsWith(".") && domainValidator.isValidTld(domain));
+            return domainValidator.isValid(domain) || !domain.startsWith(".") && domainValidator.isValidTld(domain);
         }
         return domainValidator.isValid(domain);
     }
diff --git a/src/main/java/org/apache/commons/validator/routines/FloatValidator.java b/src/main/java/org/apache/commons/validator/routines/FloatValidator.java
index f1c22b5..ede8391 100644
--- a/src/main/java/org/apache/commons/validator/routines/FloatValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/FloatValidator.java
@@ -68,7 +68,7 @@
     private static final FloatValidator VALIDATOR = new FloatValidator();
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the FloatValidator.
      */
     public static FloatValidator getInstance() {
@@ -76,7 +76,7 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance.
+     * Constructs a <i>strict</i> instance.
      */
     public FloatValidator() {
         this(true, STANDARD_FORMAT);
@@ -98,7 +98,7 @@
      *           <i>percent</i> number formats (the default).</li>
      *    </ul>
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param formatType The <code>NumberFormat</code> type to
      *        create for validation, default is STANDARD_FORMAT.
@@ -108,66 +108,16 @@
     }
 
     /**
-     * <p>Validate/convert a <code>Float</code> using the default
-     *    <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return The parsed <code>Float</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public Float validate(final String value) {
-        return (Float)parse(value, (String)null, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Float</code> using the
-     *    specified <i>pattern</i>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @return The parsed <code>Float</code> if valid or <code>null</code> if invalid.
-     */
-    public Float validate(final String value, final String pattern) {
-        return (Float)parse(value, pattern, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Float</code> using the
-     *    specified <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the number format, system default if null.
-     * @return The parsed <code>Float</code> if valid or <code>null</code> if invalid.
-     */
-    public Float validate(final String value, final Locale locale) {
-        return (Float)parse(value, (String)null, locale);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Float</code> using the
-     *    specified pattern and/ or <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>Float</code> if valid or <code>null</code> if invalid.
-     */
-    public Float validate(final String value, final String pattern, final Locale locale) {
-        return (Float)parse(value, pattern, locale);
-    }
-
-    /**
      * Check if the value is within a specified range.
      *
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final float value, final float min, final float max) {
-        return (value >= min && value <= max);
+        return value >= min && value <= max;
     }
 
     /**
@@ -176,7 +126,7 @@
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final Float value, final float min, final float max) {
@@ -184,39 +134,15 @@
     }
 
     /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final float value, final float min) {
-        return (value >= min);
-    }
-
-    /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final Float value, final float min) {
-        return minValue(value.floatValue(), min);
-    }
-
-    /**
      * Check if the value is less than or equal to a maximum.
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final float value, final float max) {
-        return (value <= max);
+        return value <= max;
     }
 
     /**
@@ -224,7 +150,7 @@
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final Float value, final float max) {
@@ -232,18 +158,42 @@
     }
 
     /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final float value, final float min) {
+        return value >= min;
+    }
+
+    /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final Float value, final float min) {
+        return minValue(value.floatValue(), min);
+    }
+
+    /**
      * <p>Perform further validation and convert the <code>Number</code> to
      * a <code>Float</code>.</p>
      *
      * @param value The parsed <code>Number</code> object created.
      * @param formatter The Format used to parse the value with.
      * @return The parsed <code>Number</code> converted to a
-     *   <code>Float</code> if valid or <code>null</code> if invalid.
+     *   <code>Float</code> if valid or {@code null} if invalid.
      */
     @Override
     protected Object processParsedValue(final Object value, final Format formatter) {
 
-        final double doubleValue = ((Number)value).doubleValue();
+        final double doubleValue = ((Number) value).doubleValue();
 
         if (doubleValue > 0) {
             if (doubleValue < Float.MIN_VALUE) {
@@ -252,7 +202,7 @@
             if (doubleValue > Float.MAX_VALUE) {
                 return null;
             }
-        } else  if (doubleValue < 0){
+        } else if (doubleValue < 0) {
             final double posDouble = doubleValue * -1;
             if (posDouble < Float.MIN_VALUE) {
                 return null;
@@ -262,8 +212,58 @@
             }
         }
 
-        return Float.valueOf((float)doubleValue);
+        return Float.valueOf((float) doubleValue);
 
     }
 
+    /**
+     * <p>Validate/convert a <code>Float</code> using the default
+     *    <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return The parsed <code>Float</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public Float validate(final String value) {
+        return (Float)parse(value, (String)null, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Float</code> using the
+     *    specified <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the number format, system default if null.
+     * @return The parsed <code>Float</code> if valid or {@code null} if invalid.
+     */
+    public Float validate(final String value, final Locale locale) {
+        return (Float)parse(value, (String)null, locale);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Float</code> using the
+     *    specified <i>pattern</i>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @return The parsed <code>Float</code> if valid or {@code null} if invalid.
+     */
+    public Float validate(final String value, final String pattern) {
+        return (Float)parse(value, pattern, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Float</code> using the
+     *    specified pattern and/ or <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>Float</code> if valid or {@code null} if invalid.
+     */
+    public Float validate(final String value, final String pattern, final Locale locale) {
+        return (Float)parse(value, pattern, locale);
+    }
+
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/IBANValidator.java b/src/main/java/org/apache/commons/validator/routines/IBANValidator.java
index f98c1c2..4db944d 100644
--- a/src/main/java/org/apache/commons/validator/routines/IBANValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/IBANValidator.java
@@ -50,10 +50,6 @@
  */
 public class IBANValidator {
 
-    private static final int SHORT_CODE_LEN = 2;
-
-    private final ConcurrentMap<String, Validator> validatorMap;
-
     /**
      * The validation class
      */
@@ -91,7 +87,7 @@
          * @param ibanLength the length of the IBAN
          * @param regexWithoutCC the regex to use to check the format, the regex MUST NOT start with the country code.
          */
-        Validator(final String countryCode, final int ibanLength, final String regexWithoutCC, String... otherCountryCodes) {
+        Validator(final String countryCode, final int ibanLength, final String regexWithoutCC, final String... otherCountryCodes) {
             if (!(countryCode.length() == 2 && Character.isUpperCase(countryCode.charAt(0)) && Character.isUpperCase(countryCode.charAt(1)))) {
                 throw new IllegalArgumentException("Invalid country Code; must be exactly 2 upper-case characters");
             }
@@ -104,9 +100,9 @@
             }
             this.countryCode = countryCode;
             this.otherCountryCodes = otherCountryCodes.clone();
-            List<String> regexList = new ArrayList<>(this.otherCountryCodes.length + 1);
+            final List<String> regexList = new ArrayList<>(this.otherCountryCodes.length + 1);
             regexList.add(countryCode + regexWithoutCC);
-            for (String otherCc : otherCountryCodes) {
+            for (final String otherCc : otherCountryCodes) {
                 regexList.add(otherCc + regexWithoutCC);
             }
             this.ibanLength = ibanLength;
@@ -124,6 +120,93 @@
         }
     }
 
+    private static final int SHORT_CODE_LEN = 2;
+
+    private static final Validator[] DEFAULT_VALIDATORS = {                   //
+            new Validator("AD", 24, "AD\\d{10}[A-Z0-9]{12}"),                 // Andorra
+            new Validator("AE", 23, "AE\\d{21}"),                             // United Arab Emirates (The)
+            new Validator("AL", 28, "AL\\d{10}[A-Z0-9]{16}"),                 // Albania
+            new Validator("AT", 20, "AT\\d{18}"),                             // Austria
+            new Validator("AZ", 28, "AZ\\d{2}[A-Z]{4}[A-Z0-9]{20}"),          // Azerbaijan
+            new Validator("BA", 20, "BA\\d{18}"),                             // Bosnia and Herzegovina
+            new Validator("BE", 16, "BE\\d{14}"),                             // Belgium
+            new Validator("BG", 22, "BG\\d{2}[A-Z]{4}\\d{6}[A-Z0-9]{8}"),     // Bulgaria
+            new Validator("BH", 22, "BH\\d{2}[A-Z]{4}[A-Z0-9]{14}"),          // Bahrain
+            new Validator("BI", 27, "BI\\d{25}"),                             // Burundi
+            new Validator("BR", 29, "BR\\d{25}[A-Z]{1}[A-Z0-9]{1}"),          // Brazil
+            new Validator("BY", 28, "BY\\d{2}[A-Z0-9]{4}\\d{4}[A-Z0-9]{16}"), // Republic of Belarus
+            new Validator("CH", 21, "CH\\d{7}[A-Z0-9]{12}"),                  // Switzerland
+            new Validator("CR", 22, "CR\\d{20}"),                             // Costa Rica
+            new Validator("CY", 28, "CY\\d{10}[A-Z0-9]{16}"),                 // Cyprus
+            new Validator("CZ", 24, "CZ\\d{22}"),                             // Czechia
+            new Validator("DE", 22, "DE\\d{20}"),                             // Germany
+            new Validator("DJ", 27, "DJ\\d{25}"),                             // Djibouti
+            new Validator("DK", 18, "DK\\d{16}"),                             // Denmark
+            new Validator("DO", 28, "DO\\d{2}[A-Z0-9]{4}\\d{20}"),            // Dominican Republic
+            new Validator("EE", 20, "EE\\d{18}"),                             // Estonia
+            new Validator("EG", 29, "EG\\d{27}"),                             // Egypt
+            new Validator("ES", 24, "ES\\d{22}"),                             // Spain
+            new Validator("FI", 18, "\\d{16}", "AX"),                         // Finland
+            new Validator("FO", 18, "FO\\d{16}"),                             // Faroe Islands
+            new Validator("FR", 27, "\\d{12}[A-Z0-9]{11}\\d{2}", "GF", "GP", "MQ", "RE", "PF", "TF", "YT", "NC", "BL", "MF", "PM", "WF"), // France
+            new Validator("GB", 22, "\\d{2}[A-Z]{4}\\d{14}", "IM", "JE", "GG"), // United Kingdom
+            new Validator("GE", 22, "GE\\d{2}[A-Z]{2}\\d{16}"),               // Georgia
+            new Validator("GI", 23, "GI\\d{2}[A-Z]{4}[A-Z0-9]{15}"),          // Gibraltar
+            new Validator("GL", 18, "GL\\d{16}"),                             // Greenland
+            new Validator("GR", 27, "GR\\d{9}[A-Z0-9]{16}"),                  // Greece
+            new Validator("GT", 28, "GT\\d{2}[A-Z0-9]{24}"),                  // Guatemala
+            new Validator("HR", 21, "HR\\d{19}"),                             // Croatia
+            new Validator("HU", 28, "HU\\d{26}"),                             // Hungary
+            new Validator("IE", 22, "IE\\d{2}[A-Z]{4}\\d{14}"),               // Ireland
+            new Validator("IL", 23, "IL\\d{21}"),                             // Israel
+            new Validator("IQ", 23, "IQ\\d{2}[A-Z]{4}\\d{15}"),               // Iraq
+            new Validator("IS", 26, "IS\\d{24}"),                             // Iceland
+            new Validator("IT", 27, "IT\\d{2}[A-Z]{1}\\d{10}[A-Z0-9]{12}"),   // Italy
+            new Validator("JO", 30, "JO\\d{2}[A-Z]{4}\\d{4}[A-Z0-9]{18}"),    // Jordan
+            new Validator("KW", 30, "KW\\d{2}[A-Z]{4}[A-Z0-9]{22}"),          // Kuwait
+            new Validator("KZ", 20, "KZ\\d{5}[A-Z0-9]{13}"),                  // Kazakhstan
+            new Validator("LB", 28, "LB\\d{6}[A-Z0-9]{20}"),                  // Lebanon
+            new Validator("LC", 32, "LC\\d{2}[A-Z]{4}[A-Z0-9]{24}"),          // Saint Lucia
+            new Validator("LI", 21, "LI\\d{7}[A-Z0-9]{12}"),                  // Liechtenstein
+            new Validator("LT", 20, "LT\\d{18}"),                             // Lithuania
+            new Validator("LU", 20, "LU\\d{5}[A-Z0-9]{13}"),                  // Luxembourg
+            new Validator("LV", 21, "LV\\d{2}[A-Z]{4}[A-Z0-9]{13}"),          // Latvia
+            new Validator("LY", 25, "LY\\d{23}"),                             // Libya
+            new Validator("MC", 27, "MC\\d{12}[A-Z0-9]{11}\\d{2}"),           // Monaco
+            new Validator("MD", 24, "MD\\d{2}[A-Z0-9]{20}"),                  // Moldova
+            new Validator("ME", 22, "ME\\d{20}"),                             // Montenegro
+            new Validator("MK", 19, "MK\\d{5}[A-Z0-9]{10}\\d{2}"),            // Macedonia
+            new Validator("MR", 27, "MR\\d{25}"),                             // Mauritania
+            new Validator("MT", 31, "MT\\d{2}[A-Z]{4}\\d{5}[A-Z0-9]{18}"),    // Malta
+            new Validator("MU", 30, "MU\\d{2}[A-Z]{4}\\d{19}[A-Z]{3}"),       // Mauritius
+            new Validator("NL", 18, "NL\\d{2}[A-Z]{4}\\d{10}"),               // Netherlands (The)
+            new Validator("NO", 15, "NO\\d{13}"),                             // Norway
+            new Validator("PK", 24, "PK\\d{2}[A-Z]{4}[A-Z0-9]{16}"),          // Pakistan
+            new Validator("PL", 28, "PL\\d{26}"),                             // Poland
+            new Validator("PS", 29, "PS\\d{2}[A-Z]{4}[A-Z0-9]{21}"),          // Palestine, State of
+            new Validator("PT", 25, "PT\\d{23}"),                             // Portugal
+            new Validator("QA", 29, "QA\\d{2}[A-Z]{4}[A-Z0-9]{21}"),          // Qatar
+            new Validator("RO", 24, "RO\\d{2}[A-Z]{4}[A-Z0-9]{16}"),          // Romania
+            new Validator("RS", 22, "RS\\d{20}"),                             // Serbia
+            new Validator("RU", 33, "RU\\d{31}"),                             // Russia
+            new Validator("SA", 24, "SA\\d{4}[A-Z0-9]{18}"),                  // Saudi Arabia
+            new Validator("SC", 31, "SC\\d{2}[A-Z]{4}\\d{20}[A-Z]{3}"),       // Seychelles
+            new Validator("SD", 18, "SD\\d{16}"),                             // Sudan
+            new Validator("SE", 24, "SE\\d{22}"),                             // Sweden
+            new Validator("SI", 19, "SI\\d{17}"),                             // Slovenia
+            new Validator("SK", 24, "SK\\d{22}"),                             // Slovakia
+            new Validator("SM", 27, "SM\\d{2}[A-Z]{1}\\d{10}[A-Z0-9]{12}"),   // San Marino
+            new Validator("ST", 25, "ST\\d{23}"),                             // Sao Tome and Principe
+            new Validator("SV", 28, "SV\\d{2}[A-Z]{4}\\d{20}"),               // El Salvador
+            new Validator("TL", 23, "TL\\d{21}"),                             // Timor-Leste
+            new Validator("TN", 24, "TN\\d{22}"),                             // Tunisia
+            new Validator("TR", 26, "TR\\d{8}[A-Z0-9]{16}"),                  // Turkey
+            new Validator("UA", 29, "UA\\d{8}[A-Z0-9]{19}"),                  // Ukraine
+            new Validator("VA", 22, "VA\\d{20}"),                             // Vatican City State
+            new Validator("VG", 24, "VG\\d{2}[A-Z]{4}\\d{16}"),               // Virgin Islands
+            new Validator("XK", 20, "XK\\d{18}"),                             // Kosovo
+    };
+
     /*
      * Wikipedia [1] says that only uppercase is allowed.
      * The SWIFT PDF file [2] implies that lower case is allowed.
@@ -152,96 +235,11 @@
      * [3] http://www.europeanpaymentscouncil.eu/documents/ECBS%20IBAN%20standard%20EBS204_V3.2.pdf
      */
 
-    private static final Validator[] DEFAULT_VALIDATORS = {
-            new Validator("AD", 24, "AD\\d{10}[A-Z0-9]{12}"                  ), // Andorra
-            new Validator("AE", 23, "AE\\d{21}"                              ), // United Arab Emirates (The)
-            new Validator("AL", 28, "AL\\d{10}[A-Z0-9]{16}"                  ), // Albania
-            new Validator("AT", 20, "AT\\d{18}"                              ), // Austria
-            new Validator("AZ", 28, "AZ\\d{2}[A-Z]{4}[A-Z0-9]{20}"           ), // Azerbaijan
-            new Validator("BA", 20, "BA\\d{18}"                              ), // Bosnia and Herzegovina
-            new Validator("BE", 16, "BE\\d{14}"                              ), // Belgium
-            new Validator("BG", 22, "BG\\d{2}[A-Z]{4}\\d{6}[A-Z0-9]{8}"      ), // Bulgaria
-            new Validator("BH", 22, "BH\\d{2}[A-Z]{4}[A-Z0-9]{14}"           ), // Bahrain
-            new Validator("BI", 27, "BI\\d{25}"                              ), // Burundi
-            new Validator("BR", 29, "BR\\d{25}[A-Z]{1}[A-Z0-9]{1}"           ), // Brazil
-            new Validator("BY", 28, "BY\\d{2}[A-Z0-9]{4}\\d{4}[A-Z0-9]{16}"  ), // Republic of Belarus
-            new Validator("CH", 21, "CH\\d{7}[A-Z0-9]{12}"                   ), // Switzerland
-            new Validator("CR", 22, "CR\\d{20}"                              ), // Costa Rica
-            new Validator("CY", 28, "CY\\d{10}[A-Z0-9]{16}"                  ), // Cyprus
-            new Validator("CZ", 24, "CZ\\d{22}"                              ), // Czechia
-            new Validator("DE", 22, "DE\\d{20}"                              ), // Germany
-            new Validator("DJ", 27, "DJ\\d{25}"                              ), // Djibouti
-            new Validator("DK", 18, "DK\\d{16}"                              ), // Denmark
-            new Validator("DO", 28, "DO\\d{2}[A-Z0-9]{4}\\d{20}"             ), // Dominican Republic
-            new Validator("EE", 20, "EE\\d{18}"                              ), // Estonia
-            new Validator("EG", 29, "EG\\d{27}"                              ), // Egypt
-            new Validator("ES", 24, "ES\\d{22}"                              ), // Spain
-            new Validator("FI", 18, "\\d{16}", "AX"                          ), // Finland
-            new Validator("FO", 18, "FO\\d{16}"                              ), // Faroe Islands
-            new Validator("FR", 27, "\\d{12}[A-Z0-9]{11}\\d{2}", "GF", "GP", "MQ", "RE", "PF", "TF", "YT", "NC", "BL", "MF", "PM", "WF"), // France
-            new Validator("GB", 22, "\\d{2}[A-Z]{4}\\d{14}", "IM", "JE", "GG"), // United Kingdom
-            new Validator("GE", 22, "GE\\d{2}[A-Z]{2}\\d{16}"                ), // Georgia
-            new Validator("GI", 23, "GI\\d{2}[A-Z]{4}[A-Z0-9]{15}"           ), // Gibraltar
-            new Validator("GL", 18, "GL\\d{16}"                              ), // Greenland
-            new Validator("GR", 27, "GR\\d{9}[A-Z0-9]{16}"                   ), // Greece
-            new Validator("GT", 28, "GT\\d{2}[A-Z0-9]{24}"                   ), // Guatemala
-            new Validator("HR", 21, "HR\\d{19}"                              ), // Croatia
-            new Validator("HU", 28, "HU\\d{26}"                              ), // Hungary
-            new Validator("IE", 22, "IE\\d{2}[A-Z]{4}\\d{14}"                ), // Ireland
-            new Validator("IL", 23, "IL\\d{21}"                              ), // Israel
-            new Validator("IQ", 23, "IQ\\d{2}[A-Z]{4}\\d{15}"                ), // Iraq
-            new Validator("IS", 26, "IS\\d{24}"                              ), // Iceland
-            new Validator("IT", 27, "IT\\d{2}[A-Z]{1}\\d{10}[A-Z0-9]{12}"    ), // Italy
-            new Validator("JO", 30, "JO\\d{2}[A-Z]{4}\\d{4}[A-Z0-9]{18}"     ), // Jordan
-            new Validator("KW", 30, "KW\\d{2}[A-Z]{4}[A-Z0-9]{22}"           ), // Kuwait
-            new Validator("KZ", 20, "KZ\\d{5}[A-Z0-9]{13}"                   ), // Kazakhstan
-            new Validator("LB", 28, "LB\\d{6}[A-Z0-9]{20}"                   ), // Lebanon
-            new Validator("LC", 32, "LC\\d{2}[A-Z]{4}[A-Z0-9]{24}"           ), // Saint Lucia
-            new Validator("LI", 21, "LI\\d{7}[A-Z0-9]{12}"                   ), // Liechtenstein
-            new Validator("LT", 20, "LT\\d{18}"                              ), // Lithuania
-            new Validator("LU", 20, "LU\\d{5}[A-Z0-9]{13}"                   ), // Luxembourg
-            new Validator("LV", 21, "LV\\d{2}[A-Z]{4}[A-Z0-9]{13}"           ), // Latvia
-            new Validator("LY", 25, "LY\\d{23}"                              ), // Libya
-            new Validator("MC", 27, "MC\\d{12}[A-Z0-9]{11}\\d{2}"            ), // Monaco
-            new Validator("MD", 24, "MD\\d{2}[A-Z0-9]{20}"                   ), // Moldova
-            new Validator("ME", 22, "ME\\d{20}"                              ), // Montenegro
-            new Validator("MK", 19, "MK\\d{5}[A-Z0-9]{10}\\d{2}"             ), // Macedonia
-            new Validator("MR", 27, "MR\\d{25}"                              ), // Mauritania
-            new Validator("MT", 31, "MT\\d{2}[A-Z]{4}\\d{5}[A-Z0-9]{18}"     ), // Malta
-            new Validator("MU", 30, "MU\\d{2}[A-Z]{4}\\d{19}[A-Z]{3}"        ), // Mauritius
-            new Validator("NL", 18, "NL\\d{2}[A-Z]{4}\\d{10}"                ), // Netherlands (The)
-            new Validator("NO", 15, "NO\\d{13}"                              ), // Norway
-            new Validator("PK", 24, "PK\\d{2}[A-Z]{4}[A-Z0-9]{16}"           ), // Pakistan
-            new Validator("PL", 28, "PL\\d{26}"                              ), // Poland
-            new Validator("PS", 29, "PS\\d{2}[A-Z]{4}[A-Z0-9]{21}"           ), // Palestine, State of
-            new Validator("PT", 25, "PT\\d{23}"                              ), // Portugal
-            new Validator("QA", 29, "QA\\d{2}[A-Z]{4}[A-Z0-9]{21}"           ), // Qatar
-            new Validator("RO", 24, "RO\\d{2}[A-Z]{4}[A-Z0-9]{16}"           ), // Romania
-            new Validator("RS", 22, "RS\\d{20}"                              ), // Serbia
-            new Validator("RU", 33, "RU\\d{31}"                              ), // Russia
-            new Validator("SA", 24, "SA\\d{4}[A-Z0-9]{18}"                   ), // Saudi Arabia
-            new Validator("SC", 31, "SC\\d{2}[A-Z]{4}\\d{20}[A-Z]{3}"        ), // Seychelles
-            new Validator("SD", 18, "SD\\d{16}"                              ), // Sudan
-            new Validator("SE", 24, "SE\\d{22}"                              ), // Sweden
-            new Validator("SI", 19, "SI\\d{17}"                              ), // Slovenia
-            new Validator("SK", 24, "SK\\d{22}"                              ), // Slovakia
-            new Validator("SM", 27, "SM\\d{2}[A-Z]{1}\\d{10}[A-Z0-9]{12}"    ), // San Marino
-            new Validator("ST", 25, "ST\\d{23}"                              ), // Sao Tome and Principe
-            new Validator("SV", 28, "SV\\d{2}[A-Z]{4}\\d{20}"                ), // El Salvador
-            new Validator("TL", 23, "TL\\d{21}"                              ), // Timor-Leste
-            new Validator("TN", 24, "TN\\d{22}"                              ), // Tunisia
-            new Validator("TR", 26, "TR\\d{8}[A-Z0-9]{16}"                   ), // Turkey
-            new Validator("UA", 29, "UA\\d{8}[A-Z0-9]{19}"                   ), // Ukraine
-            new Validator("VA", 22, "VA\\d{20}"                              ), // Vatican City State
-            new Validator("VG", 24, "VG\\d{2}[A-Z]{4}\\d{16}"                ), // Virgin Islands
-            new Validator("XK", 20, "XK\\d{18}"                              ), // Kosovo
-    };
-
     /** The singleton instance which uses the default formats */
     public static final IBANValidator DEFAULT_IBAN_VALIDATOR = new IBANValidator();
 
     /**
-     * Return a singleton instance of the IBAN validator using the default formats
+     * Gets the singleton instance of the IBAN validator using the default formats
      *
      * @return A singleton instance of the IBAN validator
      */
@@ -249,6 +247,8 @@
         return DEFAULT_IBAN_VALIDATOR;
     }
 
+    private final ConcurrentMap<String, Validator> validatorMap;
+
     /**
      * Create a default IBAN validator.
      */
@@ -269,7 +269,7 @@
         final ConcurrentMap<String, Validator> map = new ConcurrentHashMap<>();
         for (final Validator validator : validators) {
             map.put(validator.countryCode, validator);
-            for (String otherCC : validator.otherCountryCodes) {
+            for (final String otherCC : validator.otherCountryCodes) {
                 map.put(otherCC, validator);
             }
         }
@@ -277,30 +277,6 @@
     }
 
     /**
-     * Validate an IBAN Code
-     *
-     * @param code The value validation is being performed on
-     * @return <code>true</code> if the value is valid
-     */
-    public boolean isValid(final String code) {
-        final Validator formatValidator = getValidator(code);
-        if (formatValidator == null || code.length() != formatValidator.ibanLength || !formatValidator.regexValidator.isValid(code)) {
-            return false;
-        }
-        return IBANCheckDigit.IBAN_CHECK_DIGIT.isValid(code);
-    }
-
-    /**
-     * Does the class have the required validator?
-     *
-     * @param code the code to check
-     * @return true if there is a validator
-     */
-    public boolean hasValidator(final String code) {
-        return getValidator(code) != null;
-    }
-
-    /**
      * Gets a copy of the default Validators.
      *
      * @return a copy of the default Validator array
@@ -310,7 +286,7 @@
     }
 
     /**
-     * Get the Validator for a given IBAN
+     * Gets the Validator for a given IBAN
      *
      * @param code a string starting with the ISO country code (e.g. an IBAN)
      *
@@ -325,18 +301,27 @@
     }
 
     /**
-     * Installs a validator.
-     * Will replace any existing entry which has the same countryCode
+     * Does the class have the required validator?
      *
-     * @param validator the instance to install.
-     * @return the previous Validator, or {@code null} if there was none
-     * @throws IllegalStateException if an attempt is made to modify the singleton validator
+     * @param code the code to check
+     * @return true if there is a validator
      */
-    public Validator setValidator(final Validator validator) {
-        if (this == DEFAULT_IBAN_VALIDATOR) {
-            throw new IllegalStateException("The singleton validator cannot be modified");
+    public boolean hasValidator(final String code) {
+        return getValidator(code) != null;
+    }
+
+    /**
+     * Validate an IBAN Code
+     *
+     * @param code The value validation is being performed on
+     * @return {@code true} if the value is valid
+     */
+    public boolean isValid(final String code) {
+        final Validator formatValidator = getValidator(code);
+        if (formatValidator == null || code.length() != formatValidator.ibanLength || !formatValidator.regexValidator.isValid(code)) {
+            return false;
         }
-        return validatorMap.put(validator.countryCode, validator);
+        return IBANCheckDigit.IBAN_CHECK_DIGIT.isValid(code);
     }
 
     /**
@@ -360,4 +345,19 @@
         }
         return setValidator(new Validator(countryCode, length, format));
     }
+
+    /**
+     * Installs a validator.
+     * Will replace any existing entry which has the same countryCode
+     *
+     * @param validator the instance to install.
+     * @return the previous Validator, or {@code null} if there was none
+     * @throws IllegalStateException if an attempt is made to modify the singleton validator
+     */
+    public Validator setValidator(final Validator validator) {
+        if (this == DEFAULT_IBAN_VALIDATOR) {
+            throw new IllegalStateException("The singleton validator cannot be modified");
+        }
+        return validatorMap.put(validator.countryCode, validator);
+    }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/ISBNValidator.java b/src/main/java/org/apache/commons/validator/routines/ISBNValidator.java
index e2ea4c3..6784159 100644
--- a/src/main/java/org/apache/commons/validator/routines/ISBNValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/ISBNValidator.java
@@ -31,21 +31,21 @@
  * the {@link EAN13CheckDigit} routine).
  * <p>
  * The <code>validate()</code> methods return the ISBN code with formatting
- * characters removed if valid or <code>null</code> if invalid.
+ * characters removed if valid or {@code null} if invalid.
  * <p>
  * This validator also provides the facility to convert ISBN-10 codes to
- * ISBN-13 if the <code>convert</code> property is <code>true</code>.
+ * ISBN-13 if the <code>convert</code> property is {@code true}.
  * <p>
  * From 1st January 2007 the book industry will start to use a new 13 digit
  * ISBN number (rather than this 10 digit ISBN number). ISBN-13 codes are
- * <a href="http://en.wikipedia.org/wiki/European_Article_Number">EAN</a>
+ * <a href="https://en.wikipedia.org/wiki/European_Article_Number">EAN</a>
  * codes, for more information see:</p>
  *
  * <ul>
- *   <li><a href="http://en.wikipedia.org/wiki/ISBN">Wikipedia - International
+ *   <li><a href="https://en.wikipedia.org/wiki/ISBN">Wikipedia - International
  *       Standard Book Number (ISBN)</a>.</li>
  *   <li>EAN - see
- *       <a href="http://en.wikipedia.org/wiki/European_Article_Number">Wikipedia -
+ *       <a href="https://en.wikipedia.org/wiki/European_Article_Number">Wikipedia -
  *       European Article Number</a>.</li>
  *   <li><a href="http://www.isbn.org/standards/home/isbn/transition.asp">ISBN-13
  *       Transition details</a>.</li>
@@ -80,16 +80,14 @@
      * or spaces.  The first group is 1-5 characters, second 1-7, third 1-6,
      * and fourth is 1 digit or an X.
      */
-    static final String ISBN10_REGEX     =
-                  "^(?:(\\d{9}[0-9X])|(?:" + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP + "([0-9X])))$";
+    static final String ISBN10_REGEX = "^(?:(\\d{9}[0-9X])|(?:" + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP + "([0-9X])))$";
 
     /**
      * ISBN-13 consists of 5 groups of numbers separated by either dashes (-)
      * or spaces.  The first group is 978 or 979, the second group is
      * 1-5 characters, third 1-7, fourth 1-6, and fifth is 1 digit.
      */
-    static final String ISBN13_REGEX     =
-        "^(978|979)(?:(\\d{10})|(?:" + SEP + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP + "([0-9])))$";
+    static final String ISBN13_REGEX = "^(978|979)(?:(\\d{10})|(?:" + SEP + GROUP + SEP + PUBLISHER + SEP + TITLE + SEP + "([0-9])))$";
 
     /** ISBN Code Validator (which converts ISBN-10 codes to ISBN-13 */
     private static final ISBNValidator ISBN_VALIDATOR = new ISBNValidator();
@@ -97,6 +95,28 @@
     /** ISBN Code Validator (which converts ISBN-10 codes to ISBN-13 */
     private static final ISBNValidator ISBN_VALIDATOR_NO_CONVERT = new ISBNValidator(false);
 
+    /**
+     * Gets the singleton instance of the ISBN validator which
+     * converts ISBN-10 codes to ISBN-13.
+     *
+     * @return A singleton instance of the ISBN validator.
+     */
+    public static ISBNValidator getInstance() {
+        return ISBN_VALIDATOR;
+    }
+
+    /**
+     * Gets the singleton instance of the ISBN validator specifying
+     * whether ISBN-10 codes should be converted to ISBN-13.
+     *
+     * @param convert {@code true} if valid ISBN-10 codes
+     * should be converted to ISBN-13 codes or {@code false}
+     * if valid ISBN-10 codes should be returned unchanged.
+     * @return A singleton instance of the ISBN validator.
+     */
+    public static ISBNValidator getInstance(final boolean convert) {
+        return convert ? ISBN_VALIDATOR : ISBN_VALIDATOR_NO_CONVERT;
+    }
 
     /** ISBN-10 Code Validator */
     private final CodeValidator isbn10Validator = new CodeValidator(ISBN10_REGEX, 10, ISBN10CheckDigit.ISBN10_CHECK_DIGIT);
@@ -107,30 +127,7 @@
     private final boolean convert;
 
     /**
-     * Return a singleton instance of the ISBN validator which
-     * converts ISBN-10 codes to ISBN-13.
-     *
-     * @return A singleton instance of the ISBN validator.
-     */
-    public static ISBNValidator getInstance() {
-        return ISBN_VALIDATOR;
-    }
-
-    /**
-     * Return a singleton instance of the ISBN validator specifying
-     * whether ISBN-10 codes should be converted to ISBN-13.
-     *
-     * @param convert <code>true</code> if valid ISBN-10 codes
-     * should be converted to ISBN-13 codes or <code>false</code>
-     * if valid ISBN-10 codes should be returned unchanged.
-     * @return A singleton instance of the ISBN validator.
-     */
-    public static ISBNValidator getInstance(final boolean convert) {
-        return convert ? ISBN_VALIDATOR : ISBN_VALIDATOR_NO_CONVERT;
-    }
-
-    /**
-     * Construct an ISBN validator which converts ISBN-10 codes
+     * Constructs an ISBN validator which converts ISBN-10 codes
      * to ISBN-13.
      */
     public ISBNValidator() {
@@ -138,11 +135,11 @@
     }
 
     /**
-     * Construct an ISBN validator indicating whether
+     * Constructs an ISBN validator indicating whether
      * ISBN-10 codes should be converted to ISBN-13.
      *
-     * @param convert <code>true</code> if valid ISBN-10 codes
-     * should be converted to ISBN-13 codes or <code>false</code>
+     * @param convert {@code true} if valid ISBN-10 codes
+     * should be converted to ISBN-13 codes or {@code false}
      * if valid ISBN-10 codes should be returned unchanged.
      */
     public ISBNValidator(final boolean convert) {
@@ -150,99 +147,13 @@
     }
 
     /**
-     * Check the code is either a valid ISBN-10 or ISBN-13 code.
-     *
-     * @param code The code to validate.
-     * @return <code>true</code> if a valid ISBN-10 or
-     * ISBN-13 code, otherwise <code>false</code>.
-     */
-    public boolean isValid(final String code) {
-        return isValidISBN13(code) || isValidISBN10(code);
-    }
-
-    /**
-     * Check the code is a valid ISBN-10 code.
-     *
-     * @param code The code to validate.
-     * @return <code>true</code> if a valid ISBN-10
-     * code, otherwise <code>false</code>.
-     */
-    public boolean isValidISBN10(final String code) {
-        return isbn10Validator.isValid(code);
-    }
-
-    /**
-     * Check the code is a valid ISBN-13 code.
-     *
-     * @param code The code to validate.
-     * @return <code>true</code> if a valid ISBN-13
-     * code, otherwise <code>false</code>.
-     */
-    public boolean isValidISBN13(final String code) {
-        return isbn13Validator.isValid(code);
-    }
-
-    /**
-     * Check the code is either a valid ISBN-10 or ISBN-13 code.
-     * <p>
-     * If valid, this method returns the ISBN code with
-     * formatting characters removed (i.e. space or hyphen).
-     * <p>
-     * Converts an ISBN-10 codes to ISBN-13 if
-     * <code>convertToISBN13</code> is <code>true</code>.
-     *
-     * @param code The code to validate.
-     * @return A valid ISBN code if valid, otherwise <code>null</code>.
-     */
-    public String validate(final String code) {
-        String result = validateISBN13(code);
-        if (result == null) {
-            result = validateISBN10(code);
-            if (result != null && convert) {
-                result = convertToISBN13(result);
-            }
-        }
-        return result;
-    }
-
-    /**
-     * Check the code is a valid ISBN-10 code.
-     * <p>
-     * If valid, this method returns the ISBN-10 code with
-     * formatting characters removed (i.e. space or hyphen).
-     *
-     * @param code The code to validate.
-     * @return A valid ISBN-10 code if valid,
-     * otherwise <code>null</code>.
-     */
-    public String validateISBN10(final String code) {
-        final Object result = isbn10Validator.validate(code);
-        return result == null ? null : result.toString();
-    }
-
-    /**
-     * Check the code is a valid ISBN-13 code.
-     * <p>
-     * If valid, this method returns the ISBN-13 code with
-     * formatting characters removed (i.e. space or hyphen).
-     *
-     * @param code The code to validate.
-     * @return A valid ISBN-13 code if valid,
-     * otherwise <code>null</code>.
-     */
-    public String validateISBN13(final String code) {
-        final Object result = isbn13Validator.validate(code);
-        return result == null ? null : result.toString();
-    }
-
-    /**
      * Convert an ISBN-10 code to an ISBN-13 code.
      * <p>
      * This method requires a valid ISBN-10 with NO formatting
      * characters.
      *
      * @param isbn10 The ISBN-10 code to convert
-     * @return A converted ISBN-13 code or <code>null</code>
+     * @return A converted ISBN-13 code or {@code null}
      * if the ISBN-10 code is not valid
      */
     public String convertToISBN13(final String isbn10) {
@@ -268,4 +179,90 @@
 
     }
 
+    /**
+     * Check the code is either a valid ISBN-10 or ISBN-13 code.
+     *
+     * @param code The code to validate.
+     * @return {@code true} if a valid ISBN-10 or
+     * ISBN-13 code, otherwise {@code false}.
+     */
+    public boolean isValid(final String code) {
+        return isValidISBN13(code) || isValidISBN10(code);
+    }
+
+    /**
+     * Check the code is a valid ISBN-10 code.
+     *
+     * @param code The code to validate.
+     * @return {@code true} if a valid ISBN-10
+     * code, otherwise {@code false}.
+     */
+    public boolean isValidISBN10(final String code) {
+        return isbn10Validator.isValid(code);
+    }
+
+    /**
+     * Check the code is a valid ISBN-13 code.
+     *
+     * @param code The code to validate.
+     * @return {@code true} if a valid ISBN-13
+     * code, otherwise {@code false}.
+     */
+    public boolean isValidISBN13(final String code) {
+        return isbn13Validator.isValid(code);
+    }
+
+    /**
+     * Check the code is either a valid ISBN-10 or ISBN-13 code.
+     * <p>
+     * If valid, this method returns the ISBN code with
+     * formatting characters removed (i.e. space or hyphen).
+     * <p>
+     * Converts an ISBN-10 codes to ISBN-13 if
+     * <code>convertToISBN13</code> is {@code true}.
+     *
+     * @param code The code to validate.
+     * @return A valid ISBN code if valid, otherwise {@code null}.
+     */
+    public String validate(final String code) {
+        String result = validateISBN13(code);
+        if (result == null) {
+            result = validateISBN10(code);
+            if (result != null && convert) {
+                result = convertToISBN13(result);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Check the code is a valid ISBN-10 code.
+     * <p>
+     * If valid, this method returns the ISBN-10 code with
+     * formatting characters removed (i.e. space or hyphen).
+     *
+     * @param code The code to validate.
+     * @return A valid ISBN-10 code if valid,
+     * otherwise {@code null}.
+     */
+    public String validateISBN10(final String code) {
+        final Object result = isbn10Validator.validate(code);
+        return result == null ? null : result.toString();
+    }
+
+    /**
+     * Check the code is a valid ISBN-13 code.
+     * <p>
+     * If valid, this method returns the ISBN-13 code with
+     * formatting characters removed (i.e. space or hyphen).
+     *
+     * @param code The code to validate.
+     * @return A valid ISBN-13 code if valid,
+     * otherwise {@code null}.
+     */
+    public String validateISBN13(final String code) {
+        final Object result = isbn13Validator.validate(code);
+        return result == null ? null : result.toString();
+    }
+
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/ISINValidator.java b/src/main/java/org/apache/commons/validator/routines/ISINValidator.java
index 73f091b..cc785c1 100644
--- a/src/main/java/org/apache/commons/validator/routines/ISINValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/ISINValidator.java
@@ -38,7 +38,7 @@
  * </p>
  *
  * <p>
- * See <a href="http://en.wikipedia.org/wiki/ISIN">Wikipedia - ISIN</a>
+ * See <a href="https://en.wikipedia.org/wiki/ISIN">Wikipedia - ISIN</a>
  * for more details.
  * </p>
  *
@@ -79,10 +79,9 @@
         Arrays.sort(SPECIALS); // Just in case ...
     }
 
-    private final boolean checkCountryCode;
-
     /**
-     * Return a singleton instance of the ISIN validator
+     * Gets the singleton instance of the ISIN validator.
+     *
      * @param checkCountryCode whether to check the country-code prefix or not
      * @return A singleton instance of the appropriate ISIN validator.
      */
@@ -90,16 +89,26 @@
         return checkCountryCode ? ISIN_VALIDATOR_TRUE : ISIN_VALIDATOR_FALSE;
     }
 
+    private final boolean checkCountryCode;
+
     private ISINValidator(final boolean checkCountryCode) {
         this.checkCountryCode = checkCountryCode;
     }
 
+    private boolean checkCode(final String code) {
+        return Arrays.binarySearch(CCODES, code) >= 0
+               ||
+               Arrays.binarySearch(SPECIALS, code) >= 0
+        ;
+    }
+
     /**
-     * Check the code is a valid ISIN code after any transformation
+     * Tests whether the code is a valid ISIN code after any transformation
      * by the validate routine.
+     *
      * @param code The code to validate.
-     * @return <code>true</code> if a valid ISIN
-     * code, otherwise <code>false</code>.
+     * @return {@code true} if a valid ISIN
+     * code, otherwise {@code false}.
      */
     public boolean isValid(final String code) {
         final boolean valid = VALIDATOR.isValid(code);
@@ -110,10 +119,10 @@
     }
 
     /**
-     * Check the code is valid ISIN code.
+     * Checks the code is valid ISIN code.
      *
      * @param code The code to validate.
-     * @return A valid ISIN code if valid, otherwise <code>null</code>.
+     * @return A valid ISIN code if valid, otherwise {@code null}.
      */
     public Object validate(final String code) {
         final Object validate = VALIDATOR.validate(code);
@@ -123,11 +132,4 @@
         return validate;
     }
 
-    private boolean checkCode(final String code) {
-        return Arrays.binarySearch(CCODES, code) >= 0
-               ||
-               Arrays.binarySearch(SPECIALS, code) >= 0
-        ;
-    }
-
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/ISSNValidator.java b/src/main/java/org/apache/commons/validator/routines/ISSNValidator.java
index 06263dc..9d6b41d 100644
--- a/src/main/java/org/apache/commons/validator/routines/ISSNValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/ISSNValidator.java
@@ -52,6 +52,7 @@
  * or trailing spaces before doing the validation.
  * To ensure that only a valid code (without 'ISSN ' prefix) is passed to a method,
  * use the following code:
+ * </p>
  * <pre>
  * Object valid = validator.validate(input);
  * if (valid != null) {
@@ -78,11 +79,11 @@
 
     private static final CodeValidator EAN_VALIDATOR = new CodeValidator(EAN_ISSN_REGEX, EAN_ISSN_LEN, EAN13CheckDigit.EAN13_CHECK_DIGIT);
 
-    /** ISSN Code Validator */
+    /** ISSN Code Validator. */
     private static final ISSNValidator ISSN_VALIDATOR = new ISSNValidator();
 
     /**
-     * Return a singleton instance of the ISSN validator
+     * Gets the singleton instance of the ISSN validator.
      *
      * @return A singleton instance of the ISSN validator.
      */
@@ -91,53 +92,17 @@
     }
 
     /**
-     * Check the code is a valid EAN code.
-     * <p>
-     * If valid, this method returns the EAN code
-     *
-     * @param code The code to validate.
-     * @return A valid EAN code if valid, otherwise <code>null</code>.
-     * @since 1.7
-     */
-    public Object validateEan(final String code) {
-        return EAN_VALIDATOR.validate(code);
-    }
-
-    /**
-     * Check the code is a valid ISSN code after any transformation
-     * by the validate routine.
-     * @param code The code to validate.
-     * @return <code>true</code> if a valid ISSN
-     * code, otherwise <code>false</code>.
-     */
-    public boolean isValid(final String code) {
-        return VALIDATOR.isValid(code);
-    }
-
-    /**
-     * Check the code is valid ISSN code.
-     * <p>
-     * If valid, this method returns the ISSN code with
-     * the 'ISSN ' prefix removed (if it was present)
-     *
-     * @param code The code to validate.
-     * @return A valid ISSN code if valid, otherwise <code>null</code>.
-     */
-    public Object validate(final String code) {
-        return VALIDATOR.validate(code);
-    }
-
-    /**
-     * Convert an ISSN code to an EAN-13 code.
+     * Converts an ISSN code to an EAN-13 code.
      * <p>
      * This method requires a valid ISSN code.
      * It may contain a leading 'ISSN ' prefix,
      * as the input is passed through the {@link #validate(String)}
      * method.
+     * </p>
      *
      * @param issn The ISSN code to convert
      * @param suffix the two digit suffix, e.g. "00"
-     * @return A converted EAN-13 code or <code>null</code>
+     * @return A converted EAN-13 code or {@code null}
      * if the input ISSN code is not valid
      */
     public String convertToEAN13(final String issn, final String suffix) {
@@ -153,7 +118,7 @@
 
         // Calculate the new EAN-13 code
         final String input = result.toString();
-        String ean13 = ISSN_PREFIX + input.substring(0, input.length() -1) + suffix;
+        String ean13 = ISSN_PREFIX + input.substring(0, input.length() - 1) + suffix;
         try {
             final String checkDigit = EAN13CheckDigit.EAN13_CHECK_DIGIT.calculate(ean13);
             ean13 += checkDigit;
@@ -165,14 +130,15 @@
     }
 
     /**
-     * Extract an ISSN code from an ISSN-EAN-13 code.
+     * Extracts an ISSN code from an ISSN-EAN-13 code.
      * <p>
      * This method requires a valid ISSN-EAN-13 code with NO formatting
      * characters.
-     * That is a 13 digit EAN-13 code with the '977' prefix
+     * That is a 13 digit EAN-13 code with the '977' prefix.
+     * </p>
      *
      * @param ean13 The ISSN code to convert
-     * @return A valid ISSN code or <code>null</code>
+     * @return A valid ISSN code or {@code null}
      * if the input ISSN EAN-13 code is not valid
      * @since 1.7
      */
@@ -192,13 +158,52 @@
         input = result.toString();
         try {
             //CHECKSTYLE:OFF: MagicNumber
-            final String issnBase = input.substring(3,10); // TODO: how to derive these
+            final String issnBase = input.substring(3, 10); // TODO: how to derive these
             //CHECKSTYLE:ON: MagicNumber
             final String checkDigit = ISSNCheckDigit.ISSN_CHECK_DIGIT.calculate(issnBase);
-            final String issn = issnBase + checkDigit;
-            return issn;
+            return issnBase + checkDigit;
         } catch (final CheckDigitException e) { // Should not happen
             throw new IllegalArgumentException("Check digit error for '" + ean13 + "' - " + e.getMessage());
         }
     }
+
+    /**
+     * Tests whether the code is a valid ISSN code after any transformation
+     * by the validate routine.
+     *
+     * @param code The code to validate.
+     * @return {@code true} if a valid ISSN
+     * code, otherwise {@code false}.
+     */
+    public boolean isValid(final String code) {
+        return VALIDATOR.isValid(code);
+    }
+
+    /**
+     * Checks the code is valid ISSN code.
+     * <p>
+     * If valid, this method returns the ISSN code with
+     * the 'ISSN ' prefix removed (if it was present)
+     * </p>
+     *
+     * @param code The code to validate.
+     * @return A valid ISSN code if valid, otherwise {@code null}.
+     */
+    public Object validate(final String code) {
+        return VALIDATOR.validate(code);
+    }
+
+    /**
+     * Checks the code is a valid EAN code.
+     * <p>
+     * If valid, this method returns the EAN code
+     * </p>
+     *
+     * @param code The code to validate.
+     * @return A valid EAN code if valid, otherwise {@code null}.
+     * @since 1.7
+     */
+    public Object validateEan(final String code) {
+        return EAN_VALIDATOR.validate(code);
+    }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/InetAddressValidator.java b/src/main/java/org/apache/commons/validator/routines/InetAddressValidator.java
index bb98beb..3550a43 100644
--- a/src/main/java/org/apache/commons/validator/routines/InetAddressValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/InetAddressValidator.java
@@ -21,6 +21,7 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.regex.Pattern;
 
 /**
  * <p><b>InetAddress</b> validation and conversion routines (<code>java.net.InetAddress</code>).</p>
@@ -59,9 +60,9 @@
      */
     private static final InetAddressValidator VALIDATOR = new InetAddressValidator();
 
-    /** IPv4 RegexValidator */
-    private final RegexValidator ipv4Validator = new RegexValidator(IPV4_REGEX);
+    private static final Pattern DIGITS_PATTERN = Pattern.compile("\\d{1,3}");
 
+    private static final Pattern ID_CHECK_PATTERN = Pattern.compile("[^\\s/%]+");
     /**
      * Returns the singleton instance of this validator.
      * @return the singleton instance of this validator
@@ -70,6 +71,9 @@
         return VALIDATOR;
     }
 
+    /** IPv4 RegexValidator */
+    private final RegexValidator ipv4Validator = new RegexValidator(IPV4_REGEX);
+
     /**
      * Checks if the specified string is a valid IPv4 or IPv6 address.
      * @param inetAddress the string to validate
@@ -102,7 +106,7 @@
 
             try {
                 iIpSegment = Integer.parseInt(ipSegment);
-            } catch(final NumberFormatException e) {
+            } catch (final NumberFormatException e) {
                 return false;
             }
 
@@ -134,7 +138,7 @@
             return false; // can only have one prefix specifier
         }
         if (parts.length == 2) {
-            if (!parts[1].matches("\\d{1,3}")) {
+            if (!DIGITS_PATTERN.matcher(parts[1]).matches()) {
                 return false; // not a valid number
             }
             final int bits = Integer.parseInt(parts[1]); // cannot fail because of RE check
@@ -149,16 +153,16 @@
         }
         // The id syntax is implementation independent, but it presumably cannot allow:
         // whitespace, '/' or '%'
-        if ((parts.length == 2) && !parts[1].matches("[^\\s/%]+")) {
+        if (parts.length == 2 && !ID_CHECK_PATTERN.matcher(parts[1]).matches()) {
             return false; // invalid id
         }
         inet6Address = parts[0];
         final boolean containsCompressedZeroes = inet6Address.contains("::");
-        if (containsCompressedZeroes && (inet6Address.indexOf("::") != inet6Address.lastIndexOf("::"))) {
+        if (containsCompressedZeroes && inet6Address.indexOf("::") != inet6Address.lastIndexOf("::")) {
             return false;
         }
-        if ((inet6Address.startsWith(":") && !inet6Address.startsWith("::"))
-                || (inet6Address.endsWith(":") && !inet6Address.endsWith("::"))) {
+        if (inet6Address.startsWith(":") && !inet6Address.startsWith("::")
+                || inet6Address.endsWith(":") && !inet6Address.endsWith("::")) {
             return false;
         }
         String[] octets = inet6Address.split(":");
@@ -209,7 +213,7 @@
             }
             validOctets++;
         }
-        if (validOctets > IPV6_MAX_HEX_GROUPS || (validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes)) {
+        if (validOctets > IPV6_MAX_HEX_GROUPS || validOctets < IPV6_MAX_HEX_GROUPS && !containsCompressedZeroes) {
             return false;
         }
         return true;
diff --git a/src/main/java/org/apache/commons/validator/routines/IntegerValidator.java b/src/main/java/org/apache/commons/validator/routines/IntegerValidator.java
index 99990cb..0882bac 100644
--- a/src/main/java/org/apache/commons/validator/routines/IntegerValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/IntegerValidator.java
@@ -68,7 +68,7 @@
     private static final IntegerValidator VALIDATOR = new IntegerValidator();
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the IntegerValidator.
      */
     public static IntegerValidator getInstance() {
@@ -76,7 +76,7 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance.
+     * Constructs a <i>strict</i> instance.
      */
     public IntegerValidator() {
         this(true, STANDARD_FORMAT);
@@ -98,7 +98,7 @@
      *           <i>percent</i> number formats (the default).</li>
      *    </ul>
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param formatType The <code>NumberFormat</code> type to
      *        create for validation, default is STANDARD_FORMAT.
@@ -108,66 +108,16 @@
     }
 
     /**
-     * <p>Validate/convert an <code>Integer</code> using the default
-     *    <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return The parsed <code>Integer</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public Integer validate(final String value) {
-        return (Integer)parse(value, (String)null, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert an <code>Integer</code> using the
-     *    specified <i>pattern</i>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @return The parsed <code>Integer</code> if valid or <code>null</code> if invalid.
-     */
-    public Integer validate(final String value, final String pattern) {
-        return (Integer)parse(value, pattern, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert an <code>Integer</code> using the
-     *    specified <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the number format, system default if null.
-     * @return The parsed <code>Integer</code> if valid or <code>null</code> if invalid.
-     */
-    public Integer validate(final String value, final Locale locale) {
-        return (Integer)parse(value, (String)null, locale);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Integer</code> using the
-     *    specified pattern and/ or <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>Integer</code> if valid or <code>null</code> if invalid.
-     */
-    public Integer validate(final String value, final String pattern, final Locale locale) {
-        return (Integer)parse(value, pattern, locale);
-    }
-
-    /**
      * Check if the value is within a specified range.
      *
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final int value, final int min, final int max) {
-        return (value >= min && value <= max);
+        return value >= min && value <= max;
     }
 
     /**
@@ -176,7 +126,7 @@
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final Integer value, final int min, final int max) {
@@ -184,39 +134,15 @@
     }
 
     /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final int value, final int min) {
-        return (value >= min);
-    }
-
-    /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final Integer value, final int min) {
-        return minValue(value.intValue(), min);
-    }
-
-    /**
      * Check if the value is less than or equal to a maximum.
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final int value, final int max) {
-        return (value <= max);
+        return value <= max;
     }
 
     /**
@@ -224,7 +150,7 @@
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final Integer value, final int max) {
@@ -232,13 +158,37 @@
     }
 
     /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final int value, final int min) {
+        return value >= min;
+    }
+
+    /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final Integer value, final int min) {
+        return minValue(value.intValue(), min);
+    }
+
+    /**
      * <p>Perform further validation and convert the <code>Number</code> to
      * an <code>Integer</code>.</p>
      *
      * @param value The parsed <code>Number</code> object created.
      * @param formatter The Format used to parse the value with.
      * @return The parsed <code>Number</code> converted to an
-     *   <code>Integer</code> if valid or <code>null</code> if invalid.
+     *   <code>Integer</code> if valid or {@code null} if invalid.
      */
     @Override
     protected Object processParsedValue(final Object value, final Format formatter) {
@@ -253,4 +203,54 @@
         }
         return null;
     }
+
+    /**
+     * <p>Validate/convert an <code>Integer</code> using the default
+     *    <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return The parsed <code>Integer</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public Integer validate(final String value) {
+        return (Integer)parse(value, (String)null, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert an <code>Integer</code> using the
+     *    specified <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the number format, system default if null.
+     * @return The parsed <code>Integer</code> if valid or {@code null} if invalid.
+     */
+    public Integer validate(final String value, final Locale locale) {
+        return (Integer)parse(value, (String)null, locale);
+    }
+
+    /**
+     * <p>Validate/convert an <code>Integer</code> using the
+     *    specified <i>pattern</i>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @return The parsed <code>Integer</code> if valid or {@code null} if invalid.
+     */
+    public Integer validate(final String value, final String pattern) {
+        return (Integer)parse(value, pattern, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Integer</code> using the
+     *    specified pattern and/ or <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>Integer</code> if valid or {@code null} if invalid.
+     */
+    public Integer validate(final String value, final String pattern, final Locale locale) {
+        return (Integer)parse(value, pattern, locale);
+    }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/LongValidator.java b/src/main/java/org/apache/commons/validator/routines/LongValidator.java
index f5e9dfb..079a151 100644
--- a/src/main/java/org/apache/commons/validator/routines/LongValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/LongValidator.java
@@ -67,7 +67,7 @@
     private static final LongValidator VALIDATOR = new LongValidator();
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the LongValidator.
      */
     public static LongValidator getInstance() {
@@ -75,7 +75,7 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance.
+     * Constructs a <i>strict</i> instance.
      */
     public LongValidator() {
         this(true, STANDARD_FORMAT);
@@ -97,7 +97,7 @@
      *           <i>percent</i> number formats (the default).</li>
      *    </ul>
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param formatType The <code>NumberFormat</code> type to
      *        create for validation, default is STANDARD_FORMAT.
@@ -107,66 +107,16 @@
     }
 
     /**
-     * <p>Validate/convert a <code>Long</code> using the default
-     *    <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return The parsed <code>Long</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public Long validate(final String value) {
-        return (Long)parse(value, (String)null, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Long</code> using the
-     *    specified <i>pattern</i>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @return The parsed <code>Long</code> if valid or <code>null</code> if invalid.
-     */
-    public Long validate(final String value, final String pattern) {
-        return (Long)parse(value, pattern, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Long</code> using the
-     *    specified <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the number format, system default if null.
-     * @return The parsed <code>Long</code> if valid or <code>null</code> if invalid.
-     */
-    public Long validate(final String value, final Locale locale) {
-        return (Long)parse(value, (String)null, locale);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Long</code> using the
-     *    specified pattern and/ or <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>Long</code> if valid or <code>null</code> if invalid.
-     */
-    public Long validate(final String value, final String pattern, final Locale locale) {
-        return (Long)parse(value, pattern, locale);
-    }
-
-    /**
      * Check if the value is within a specified range.
      *
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final long value, final long min, final long max) {
-        return (value >= min && value <= max);
+        return value >= min && value <= max;
     }
 
     /**
@@ -175,7 +125,7 @@
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final Long value, final long min, final long max) {
@@ -183,39 +133,15 @@
     }
 
     /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final long value, final long min) {
-        return (value >= min);
-    }
-
-    /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final Long value, final long min) {
-        return minValue(value.longValue(), min);
-    }
-
-    /**
      * Check if the value is less than or equal to a maximum.
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final long value, final long max) {
-        return (value <= max);
+        return value <= max;
     }
 
     /**
@@ -223,7 +149,7 @@
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final Long value, final long max) {
@@ -231,6 +157,30 @@
     }
 
     /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final long value, final long min) {
+        return value >= min;
+    }
+
+    /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final Long value, final long min) {
+        return minValue(value.longValue(), min);
+    }
+
+    /**
      * Convert the parsed value to a <code>Long</code>.
      *
      * @param value The parsed <code>Number</code> object created.
@@ -248,4 +198,54 @@
         return null;
 
     }
+
+    /**
+     * <p>Validate/convert a <code>Long</code> using the default
+     *    <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return The parsed <code>Long</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public Long validate(final String value) {
+        return (Long)parse(value, (String)null, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Long</code> using the
+     *    specified <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the number format, system default if null.
+     * @return The parsed <code>Long</code> if valid or {@code null} if invalid.
+     */
+    public Long validate(final String value, final Locale locale) {
+        return (Long)parse(value, (String)null, locale);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Long</code> using the
+     *    specified <i>pattern</i>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @return The parsed <code>Long</code> if valid or {@code null} if invalid.
+     */
+    public Long validate(final String value, final String pattern) {
+        return (Long)parse(value, pattern, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Long</code> using the
+     *    specified pattern and/ or <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>Long</code> if valid or {@code null} if invalid.
+     */
+    public Long validate(final String value, final String pattern, final Locale locale) {
+        return (Long)parse(value, pattern, locale);
+    }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/PercentValidator.java b/src/main/java/org/apache/commons/validator/routines/PercentValidator.java
index 089e233..635dbe9 100644
--- a/src/main/java/org/apache/commons/validator/routines/PercentValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/PercentValidator.java
@@ -56,7 +56,7 @@
     private static final BigDecimal POINT_ZERO_ONE = new BigDecimal("0.01");
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the PercentValidator.
      */
     public static BigDecimalValidator getInstance() {
@@ -64,16 +64,16 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance.
+     * Constructs a <i>strict</i> instance.
      */
     public PercentValidator() {
         this(true);
     }
 
     /**
-     * Construct an instance with the specified strict setting.
+     * Constructs an instance with the specified strict setting.
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      */
     public PercentValidator(final boolean strict) {
@@ -91,7 +91,7 @@
      *
      * @param value The value to be parsed.
      * @param formatter The Format to parse the value with.
-     * @return The parsed value if valid or <code>null</code> if invalid.
+     * @return The parsed value if valid or {@code null} if invalid.
      */
     @Override
     protected Object parse(final String value, final Format formatter) {
diff --git a/src/main/java/org/apache/commons/validator/routines/RegexValidator.java b/src/main/java/org/apache/commons/validator/routines/RegexValidator.java
index c6f25dd..7b62319 100644
--- a/src/main/java/org/apache/commons/validator/routines/RegexValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/RegexValidator.java
@@ -24,7 +24,7 @@
 /**
  * <b>Regular Expression</b> validation (using the JRE's regular expression support).
  * <p>
- * Construct the validator either for a single regular expression or a set (array) of
+ * Constructs the validator either for a single regular expression or a set (array) of
  * regular expressions. By default validation is <i>case sensitive</i> but constructors
  * are provided to allow  <i>case in-sensitive</i> validation. For example to create
  * a validator which does <i>case in-sensitive</i> validation for a set of regular
@@ -38,7 +38,7 @@
  * </pre>
  *
  * <ul>
- *   <li>Validate <code>true</code> or <code>false</code>:</li>
+ *   <li>Validate {@code true} or {@code false}:</li>
  *   <li>
  *     <ul>
  *       <li><code>boolean valid = validator.isValid(value);</code></li>
@@ -96,19 +96,6 @@
     }
 
     /**
-     * Constructs a validator for a single regular expression
-     * with the specified case sensitivity.
-     *
-     * @param regex The regular expression this validator will
-     * validate against
-     * @param caseSensitive when <code>true</code> matching is <i>case
-     * sensitive</i>, otherwise matching is <i>case in-sensitive</i>
-     */
-    public RegexValidator(final String regex, final boolean caseSensitive) {
-        this(new String[] { regex }, caseSensitive);
-    }
-
-    /**
      * Constructs a <i>case sensitive</i> validator that matches any one
      * in the array of regular expressions.
      *
@@ -120,12 +107,25 @@
     }
 
     /**
+     * Constructs a validator for a single regular expression
+     * with the specified case sensitivity.
+     *
+     * @param regex The regular expression this validator will
+     * validate against
+     * @param caseSensitive when {@code true} matching is <i>case
+     * sensitive</i>, otherwise matching is <i>case in-sensitive</i>
+     */
+    public RegexValidator(final String regex, final boolean caseSensitive) {
+        this(new String[] { regex }, caseSensitive);
+    }
+
+    /**
      * Constructs a validator that matches any one of the set of regular
      * expressions with the specified case sensitivity.
      *
      * @param regexs The set of regular expressions this validator will
      * validate against
-     * @param caseSensitive when <code>true</code> matching is <i>case
+     * @param caseSensitive when {@code true} matching is <i>case
      * sensitive</i>, otherwise matching is <i>case in-sensitive</i>
      */
     public RegexValidator(final String[] regexs, final boolean caseSensitive) {
@@ -133,7 +133,7 @@
             throw new IllegalArgumentException("Regular expressions are missing");
         }
         patterns = new Pattern[regexs.length];
-        final int flags = (caseSensitive ? 0 : Pattern.CASE_INSENSITIVE);
+        final int flags = caseSensitive ? 0 : Pattern.CASE_INSENSITIVE;
         for (int i = 0; i < regexs.length; i++) {
             if (regexs[i] == null || regexs[i].isEmpty()) {
                 throw new IllegalArgumentException("Regular expression[" + i + "] is missing");
@@ -156,8 +156,8 @@
      * Validates a value against the set of regular expressions.
      *
      * @param value The value to validate.
-     * @return <code>true</code> if the value is valid
-     * otherwise <code>false</code>.
+     * @return {@code true} if the value is valid
+     * otherwise {@code false}.
      */
     public boolean isValid(final String value) {
         if (value == null) {
@@ -177,7 +177,7 @@
      *
      * @param value The value to validate.
      * @return String array of the <i>groups</i> matched if
-     * valid or <code>null</code> if invalid
+     * valid or {@code null} if invalid
      */
     public String[] match(final String value) {
         if (value == null) {
@@ -197,39 +197,6 @@
         return null;
     }
 
-
-    /**
-     * Validates a value against the set of regular expressions
-     * returning a String value of the aggregated groups.
-     *
-     * @param value The value to validate.
-     * @return Aggregated String value comprised of the
-     * <i>groups</i> matched if valid or <code>null</code> if invalid
-     */
-    public String validate(final String value) {
-        if (value == null) {
-            return null;
-        }
-        for (final Pattern pattern : patterns) {
-            final Matcher matcher = pattern.matcher(value);
-            if (matcher.matches()) {
-                final int count = matcher.groupCount();
-                if (count == 1) {
-                    return matcher.group(1);
-                }
-                final StringBuilder buffer = new StringBuilder();
-                for (int j = 0; j < count; j++) {
-                    final String component = matcher.group(j+1);
-                    if (component != null) {
-                        buffer.append(component);
-                    }
-                }
-                return buffer.toString();
-            }
-        }
-        return null;
-    }
-
     /**
      * Provides a String representation of this validator.
      * @return A String representation of this validator.
@@ -248,4 +215,36 @@
         return buffer.toString();
     }
 
+    /**
+     * Validates a value against the set of regular expressions
+     * returning a String value of the aggregated groups.
+     *
+     * @param value The value to validate.
+     * @return Aggregated String value comprised of the
+     * <i>groups</i> matched if valid or {@code null} if invalid
+     */
+    public String validate(final String value) {
+        if (value == null) {
+            return null;
+        }
+        for (final Pattern pattern : patterns) {
+            final Matcher matcher = pattern.matcher(value);
+            if (matcher.matches()) {
+                final int count = matcher.groupCount();
+                if (count == 1) {
+                    return matcher.group(1);
+                }
+                final StringBuilder buffer = new StringBuilder();
+                for (int j = 0; j < count; j++) {
+                    final String component = matcher.group(j + 1);
+                    if (component != null) {
+                        buffer.append(component);
+                    }
+                }
+                return buffer.toString();
+            }
+        }
+        return null;
+    }
+
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/ShortValidator.java b/src/main/java/org/apache/commons/validator/routines/ShortValidator.java
index bf9ed8c..f23d676 100644
--- a/src/main/java/org/apache/commons/validator/routines/ShortValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/ShortValidator.java
@@ -68,7 +68,7 @@
     private static final ShortValidator VALIDATOR = new ShortValidator();
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the ShortValidator.
      */
     public static ShortValidator getInstance() {
@@ -76,7 +76,7 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance.
+     * Constructs a <i>strict</i> instance.
      */
     public ShortValidator() {
         this(true, STANDARD_FORMAT);
@@ -98,7 +98,7 @@
      *           <i>percent</i> number formats (the default).</li>
      *    </ul>
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param formatType The <code>NumberFormat</code> type to
      *        create for validation, default is STANDARD_FORMAT.
@@ -108,66 +108,16 @@
     }
 
     /**
-     * <p>Validate/convert a <code>Short</code> using the default
-     *    <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return The parsed <code>Short</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public Short validate(final String value) {
-        return (Short)parse(value, (String)null, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Short</code> using the
-     *    specified <i>pattern</i>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @return The parsed <code>Short</code> if valid or <code>null</code> if invalid.
-     */
-    public Short validate(final String value, final String pattern) {
-        return (Short)parse(value, pattern, (Locale)null);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Short</code> using the
-     *    specified <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the number format, system default if null.
-     * @return The parsed <code>Short</code> if valid or <code>null</code> if invalid.
-     */
-    public Short validate(final String value, final Locale locale) {
-        return (Short)parse(value, (String)null, locale);
-    }
-
-    /**
-     * <p>Validate/convert a <code>Short</code> using the
-     *    specified pattern and/ or <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>Short</code> if valid or <code>null</code> if invalid.
-     */
-    public Short validate(final String value, final String pattern, final Locale locale) {
-        return (Short)parse(value, pattern, locale);
-    }
-
-    /**
      * Check if the value is within a specified range.
      *
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final short value, final short min, final short max) {
-        return (value >= min && value <= max);
+        return value >= min && value <= max;
     }
 
     /**
@@ -176,7 +126,7 @@
      * @param value The <code>Number</code> value to check.
      * @param min The minimum value of the range.
      * @param max The maximum value of the range.
-     * @return <code>true</code> if the value is within the
+     * @return {@code true} if the value is within the
      *         specified range.
      */
     public boolean isInRange(final Short value, final short min, final short max) {
@@ -184,39 +134,15 @@
     }
 
     /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final short value, final short min) {
-        return (value >= min);
-    }
-
-    /**
-     * Check if the value is greater than or equal to a minimum.
-     *
-     * @param value The value validation is being performed on.
-     * @param min The minimum value.
-     * @return <code>true</code> if the value is greater than
-     *         or equal to the minimum.
-     */
-    public boolean minValue(final Short value, final short min) {
-        return minValue(value.shortValue(), min);
-    }
-
-    /**
      * Check if the value is less than or equal to a maximum.
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final short value, final short max) {
-        return (value <= max);
+        return value <= max;
     }
 
     /**
@@ -224,7 +150,7 @@
      *
      * @param value The value validation is being performed on.
      * @param max The maximum value.
-     * @return <code>true</code> if the value is less than
+     * @return {@code true} if the value is less than
      *         or equal to the maximum.
      */
     public boolean maxValue(final Short value, final short max) {
@@ -232,13 +158,37 @@
     }
 
     /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final short value, final short min) {
+        return value >= min;
+    }
+
+    /**
+     * Check if the value is greater than or equal to a minimum.
+     *
+     * @param value The value validation is being performed on.
+     * @param min The minimum value.
+     * @return {@code true} if the value is greater than
+     *         or equal to the minimum.
+     */
+    public boolean minValue(final Short value, final short min) {
+        return minValue(value.shortValue(), min);
+    }
+
+    /**
      * <p>Perform further validation and convert the <code>Number</code> to
      * a <code>Short</code>.</p>
      *
      * @param value The parsed <code>Number</code> object created.
      * @param formatter The Format used to parse the value with.
      * @return The parsed <code>Number</code> converted to a
-     *   <code>Short</code> if valid or <code>null</code> if invalid.
+     *   <code>Short</code> if valid or {@code null} if invalid.
      */
     @Override
     protected Object processParsedValue(final Object value, final Format formatter) {
@@ -251,4 +201,54 @@
         }
         return Short.valueOf((short)longValue);
     }
+
+    /**
+     * <p>Validate/convert a <code>Short</code> using the default
+     *    <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return The parsed <code>Short</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public Short validate(final String value) {
+        return (Short)parse(value, (String)null, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Short</code> using the
+     *    specified <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the number format, system default if null.
+     * @return The parsed <code>Short</code> if valid or {@code null} if invalid.
+     */
+    public Short validate(final String value, final Locale locale) {
+        return (Short)parse(value, (String)null, locale);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Short</code> using the
+     *    specified <i>pattern</i>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @return The parsed <code>Short</code> if valid or {@code null} if invalid.
+     */
+    public Short validate(final String value, final String pattern) {
+        return (Short)parse(value, pattern, (Locale)null);
+    }
+
+    /**
+     * <p>Validate/convert a <code>Short</code> using the
+     *    specified pattern and/ or <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>Short</code> if valid or {@code null} if invalid.
+     */
+    public Short validate(final String value, final String pattern, final Locale locale) {
+        return (Short)parse(value, pattern, locale);
+    }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/TimeValidator.java b/src/main/java/org/apache/commons/validator/routines/TimeValidator.java
index b89bcf6..eee7ad4 100644
--- a/src/main/java/org/apache/commons/validator/routines/TimeValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/TimeValidator.java
@@ -88,7 +88,7 @@
     private static final TimeValidator VALIDATOR = new TimeValidator();
 
     /**
-     * Return a singleton instance of this validator.
+     * Gets the singleton instance of this validator.
      * @return A singleton instance of the TimeValidator.
      */
     public static TimeValidator getInstance() {
@@ -96,7 +96,7 @@
     }
 
     /**
-     * Construct a <i>strict</i> instance with <i>short</i>
+     * Constructs a <i>strict</i> instance with <i>short</i>
      * time style.
      */
     public TimeValidator() {
@@ -104,10 +104,10 @@
     }
 
     /**
-     * Construct an instance with the specified <i>strict</i>
+     * Constructs an instance with the specified <i>strict</i>
      * and <i>time style</i> parameters.
      *
-     * @param strict <code>true</code> if strict
+     * @param strict {@code true} if strict
      *        <code>Format</code> parsing should be used.
      * @param timeStyle the time style to use for Locale validation.
      */
@@ -116,148 +116,6 @@
     }
 
     /**
-     * <p>Validate/convert a time using the default <code>Locale</code>
-     *    and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code>
-     *  if invalid.
-     */
-    public Calendar validate(final String value) {
-        return (Calendar)parse(value, (String)null, (Locale)null, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a time using the specified <code>TimeZone</code>
-     *    and default <code>Locale</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param timeZone The Time Zone used to parse the time, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final TimeZone timeZone) {
-        return (Calendar)parse(value, (String)null, (Locale)null, timeZone);
-    }
-
-    /**
-     * <p>Validate/convert a time using the specified <i>pattern</i> and
-     *    default <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final String pattern) {
-        return (Calendar)parse(value, pattern, (Locale)null, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a time using the specified <i>pattern</i>
-     *    and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against.
-     * @param timeZone The Time Zone used to parse the time, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final String pattern, final TimeZone timeZone) {
-        return (Calendar)parse(value, pattern, (Locale)null, timeZone);
-    }
-
-    /**
-     * <p>Validate/convert a time using the specified <code>Locale</code>
-     *    default <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the time format, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final Locale locale) {
-        return (Calendar)parse(value, (String)null, locale, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a time using the specified <code>Locale</code>
-     *    and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param locale The locale to use for the time format, system default if null.
-     * @param timeZone The Time Zone used to parse the time, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final Locale locale, final TimeZone timeZone) {
-        return (Calendar)parse(value, (String)null, locale, timeZone);
-    }
-
-    /**
-     * <p>Validate/convert a time using the specified pattern and <code>Locale</code>
-     *    and the default <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final String pattern, final Locale locale) {
-        return (Calendar)parse(value, pattern, locale, (TimeZone)null);
-    }
-
-    /**
-     * <p>Validate/convert a time using the specified pattern, <code>Locale</code>
-     *    and <code>TimeZone</code>.
-     *
-     * @param value The value validation is being performed on.
-     * @param pattern The pattern used to validate the value against, or the
-     *        default for the <code>Locale</code> if <code>null</code>.
-     * @param locale The locale to use for the date format, system default if null.
-     * @param timeZone The Time Zone used to parse the date, system default if null.
-     * @return The parsed <code>Calendar</code> if valid or <code>null</code> if invalid.
-     */
-    public Calendar validate(final String value, final String pattern, final Locale locale, final TimeZone timeZone) {
-        return (Calendar)parse(value, pattern, locale, timeZone);
-    }
-
-    /**
-     * <p>Compare Times (hour, minute, second and millisecond - not date).</p>
-     *
-     * @param value The <code>Calendar</code> value to check.
-     * @param compare The <code>Calendar</code> to compare the value to.
-     * @return Zero if the hours are equal, -1 if first
-     * time is less than the seconds and +1 if the first
-     * time is greater than.
-     */
-    public int compareTime(final Calendar value, final Calendar compare) {
-        return compareTime(value, compare, Calendar.MILLISECOND);
-    }
-
-    /**
-     * <p>Compare Seconds (hours, minutes and seconds).</p>
-     *
-     * @param value The <code>Calendar</code> value to check.
-     * @param compare The <code>Calendar</code> to compare the value to.
-     * @return Zero if the hours are equal, -1 if first
-     * parameter's seconds are less than the seconds and +1 if the first
-     * parameter's seconds are greater than.
-     */
-    public int compareSeconds(final Calendar value, final Calendar compare) {
-        return compareTime(value, compare, Calendar.SECOND);
-    }
-
-    /**
-     * <p>Compare Minutes (hours and minutes).</p>
-     *
-     * @param value The <code>Calendar</code> value to check.
-     * @param compare The <code>Calendar</code> to compare the value to.
-     * @return Zero if the hours are equal, -1 if first
-     * parameter's minutes are less than the seconds and +1 if the first
-     * parameter's minutes are greater than.
-     */
-    public int compareMinutes(final Calendar value, final Calendar compare) {
-        return compareTime(value, compare, Calendar.MINUTE);
-    }
-
-    /**
      * <p>Compare Hours.</p>
      *
      * @param value The <code>Calendar</code> value to check.
@@ -271,6 +129,45 @@
     }
 
     /**
+     * <p>Compare Minutes (hours and minutes).</p>
+     *
+     * @param value The <code>Calendar</code> value to check.
+     * @param compare The <code>Calendar</code> to compare the value to.
+     * @return Zero if the hours are equal, -1 if first
+     * parameter's minutes are less than the seconds and +1 if the first
+     * parameter's minutes are greater than.
+     */
+    public int compareMinutes(final Calendar value, final Calendar compare) {
+        return compareTime(value, compare, Calendar.MINUTE);
+    }
+
+    /**
+     * <p>Compare Seconds (hours, minutes and seconds).</p>
+     *
+     * @param value The <code>Calendar</code> value to check.
+     * @param compare The <code>Calendar</code> to compare the value to.
+     * @return Zero if the hours are equal, -1 if first
+     * parameter's seconds are less than the seconds and +1 if the first
+     * parameter's seconds are greater than.
+     */
+    public int compareSeconds(final Calendar value, final Calendar compare) {
+        return compareTime(value, compare, Calendar.SECOND);
+    }
+
+    /**
+     * <p>Compare Times (hour, minute, second and millisecond - not date).</p>
+     *
+     * @param value The <code>Calendar</code> value to check.
+     * @param compare The <code>Calendar</code> to compare the value to.
+     * @return Zero if the hours are equal, -1 if first
+     * time is less than the seconds and +1 if the first
+     * time is greater than.
+     */
+    public int compareTime(final Calendar value, final Calendar compare) {
+        return compareTime(value, compare, Calendar.MILLISECOND);
+    }
+
+    /**
      * <p>Convert the parsed <code>Date</code> to a <code>Calendar</code>.</p>
      *
      * @param value The parsed <code>Date</code> object created.
@@ -281,4 +178,107 @@
     protected Object processParsedValue(final Object value, final Format formatter) {
         return ((DateFormat)formatter).getCalendar();
     }
+
+    /**
+     * <p>Validate/convert a time using the default <code>Locale</code>
+     *    and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @return The parsed <code>Calendar</code> if valid or {@code null}
+     *  if invalid.
+     */
+    public Calendar validate(final String value) {
+        return (Calendar)parse(value, (String)null, (Locale)null, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a time using the specified <code>Locale</code>
+     *    default <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the time format, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final Locale locale) {
+        return (Calendar)parse(value, (String)null, locale, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a time using the specified <code>Locale</code>
+     *    and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param locale The locale to use for the time format, system default if null.
+     * @param timeZone The Time Zone used to parse the time, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final Locale locale, final TimeZone timeZone) {
+        return (Calendar)parse(value, (String)null, locale, timeZone);
+    }
+
+    /**
+     * <p>Validate/convert a time using the specified <i>pattern</i> and
+     *    default <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final String pattern) {
+        return (Calendar)parse(value, pattern, (Locale)null, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a time using the specified pattern and <code>Locale</code>
+     *    and the default <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final String pattern, final Locale locale) {
+        return (Calendar)parse(value, pattern, locale, (TimeZone)null);
+    }
+
+    /**
+     * <p>Validate/convert a time using the specified pattern, <code>Locale</code>
+     *    and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against, or the
+     *        default for the <code>Locale</code> if {@code null}.
+     * @param locale The locale to use for the date format, system default if null.
+     * @param timeZone The Time Zone used to parse the date, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final String pattern, final Locale locale, final TimeZone timeZone) {
+        return (Calendar)parse(value, pattern, locale, timeZone);
+    }
+
+    /**
+     * <p>Validate/convert a time using the specified <i>pattern</i>
+     *    and <code>TimeZone</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param pattern The pattern used to validate the value against.
+     * @param timeZone The Time Zone used to parse the time, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final String pattern, final TimeZone timeZone) {
+        return (Calendar)parse(value, pattern, (Locale)null, timeZone);
+    }
+
+    /**
+     * <p>Validate/convert a time using the specified <code>TimeZone</code>
+     *    and default <code>Locale</code>.
+     *
+     * @param value The value validation is being performed on.
+     * @param timeZone The Time Zone used to parse the time, system default if null.
+     * @return The parsed <code>Calendar</code> if valid or {@code null} if invalid.
+     */
+    public Calendar validate(final String value, final TimeZone timeZone) {
+        return (Calendar)parse(value, (String)null, (Locale)null, timeZone);
+    }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/UrlValidator.java b/src/main/java/org/apache/commons/validator/routines/UrlValidator.java
index 9b0258d..62fb169 100644
--- a/src/main/java/org/apache/commons/validator/routines/UrlValidator.java
+++ b/src/main/java/org/apache/commons/validator/routines/UrlValidator.java
@@ -39,7 +39,7 @@
  * </ul>
  *
  * <p>Originally based in on php script by Debbie Dyer, validation.php v1.2b, Date: 03/07/02,
- * http://javascript.internet.com. However, this validation now bears little resemblance
+ * https://javascript.internet.com. However, this validation now bears little resemblance
  * to the php original.</p>
  * <pre>
  *   Example of usage:
@@ -96,7 +96,7 @@
     public static final long NO_FRAGMENTS = 1 << 2;
 
     /**
-     * Allow local URLs, such as http://localhost/ or http://machine/ .
+     * Allow local URLs, such as https://localhost/ or https://machine/ .
      * This enables a broad-brush check, for complex local machine name
      *  validation requirements you should create your validator with
      *  a {@link RegexValidator} instead ({@link #UrlValidator(RegexValidator, long)})
@@ -121,13 +121,15 @@
     // sub-delims    = "!" / "$" / "&" / "'" / "(" / ")" / "*" / "+" / "," / ";" / "="
     // We assume that password has the same valid chars as user info
     private static final String USERINFO_CHARS_REGEX = "[a-zA-Z0-9%-._~!$&'()*+,;=]";
+
     // since neither ':' nor '@' are allowed chars, we don't need to use non-greedy matching
     private static final String USERINFO_FIELD_REGEX =
             USERINFO_CHARS_REGEX + "+" + // At least one character for the name
             "(?::" + USERINFO_CHARS_REGEX + "*)?@"; // colon and password may be absent
+
     private static final String AUTHORITY_REGEX =
-            "(?:\\[("+IPV6_REGEX+")\\]|(?:(?:"+USERINFO_FIELD_REGEX+")?([" + AUTHORITY_CHARS_REGEX + "]*)))(?::(\\d*))?(.*)?";
-    //             1                          e.g. user:pass@          2                                         3       4
+            "(?:\\[(" + IPV6_REGEX + ")\\]|(?:(?:" + USERINFO_FIELD_REGEX + ")?([" + AUTHORITY_CHARS_REGEX + "]*)))(?::(\\d*))?(.*)?";
+    //             1                                 e.g. user:pass@           2                                       3       4
     private static final Pattern AUTHORITY_PATTERN = Pattern.compile(AUTHORITY_REGEX);
 
     private static final int PARSE_AUTHORITY_IPV6 = 1;
@@ -148,22 +150,6 @@
     private static final Pattern QUERY_PATTERN = Pattern.compile(QUERY_REGEX);
 
     /**
-     * Holds the set of current validation options.
-     */
-    private final long options;
-
-    /**
-     * The set of schemes that are allowed to be in a URL.
-     */
-    private final Set<String> allowedSchemes; // Must be lower-case
-
-    /**
-     * Regular expressions used to manually validate authorities if IANA
-     * domain name validation isn't desired.
-     */
-    private final RegexValidator authorityValidator;
-
-    /**
      * If no schemes are provided, default to this set.
      */
     private static final String[] DEFAULT_SCHEMES = {"http", "https", "ftp"}; // Must be lower-case
@@ -181,6 +167,35 @@
         return DEFAULT_URL_VALIDATOR;
     }
 
+    /**
+     * Tests whether the given flag is on.  If the flag is not a power of 2
+     * (e.g. 3) this tests whether the combination of flags is on.
+     *
+     * @param flag Flag value to check.
+     * @param options what to check
+     *
+     * @return whether the specified flag value is on.
+     */
+    private static boolean isOn(final long flag, final long options) {
+        return (options & flag) > 0;
+    }
+
+    /**
+     * Holds the set of current validation options.
+     */
+    private final long options;
+
+    /**
+     * The set of schemes that are allowed to be in a URL.
+     */
+    private final Set<String> allowedSchemes; // Must be lower-case
+
+    /**
+     * Regular expressions used to manually validate authorities if IANA
+     * domain name validation isn't desired.
+     */
+    private final RegexValidator authorityValidator;
+
     private final DomainValidator domainValidator;
 
     /**
@@ -191,6 +206,29 @@
     }
 
     /**
+     * Initialize a UrlValidator with the given validation options.
+     * @param options The options should be set using the public constants declared in
+     * this class.  To set multiple options you simply add them together.  For example,
+     * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options.
+     */
+    public UrlValidator(final long options) {
+        this(null, null, options);
+    }
+
+    /**
+     * Initialize a UrlValidator with the given validation options.
+     * @param authorityValidator Regular expression validator used to validate the authority part
+     * This allows the user to override the standard set of domains.
+     * @param options Validation options. Set using the public constants of this class.
+     * To set multiple options, simply add them together:
+     * <p><code>ALLOW_2_SLASHES + NO_FRAGMENTS</code></p>
+     * enables both of those options.
+     */
+    public UrlValidator(final RegexValidator authorityValidator, final long options) {
+        this(null, authorityValidator, options);
+    }
+
+    /**
      * Behavior of validation is modified by passing in several strings options:
      * @param schemes Pass in one or more URL schemes to consider valid, passing in
      *        a null will default to "http,https,ftp" being valid.
@@ -203,16 +241,6 @@
     }
 
     /**
-     * Initialize a UrlValidator with the given validation options.
-     * @param options The options should be set using the public constants declared in
-     * this class.  To set multiple options you simply add them together.  For example,
-     * ALLOW_2_SLASHES + NO_FRAGMENTS enables both of those options.
-     */
-    public UrlValidator(final long options) {
-        this(null, null, options);
-    }
-
-    /**
      * Behavior of validation is modified by passing in options:
      * @param schemes The set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set.
      * @param options The options should be set using the public constants declared in
@@ -224,19 +252,6 @@
     }
 
     /**
-     * Initialize a UrlValidator with the given validation options.
-     * @param authorityValidator Regular expression validator used to validate the authority part
-     * This allows the user to override the standard set of domains.
-     * @param options Validation options. Set using the public constants of this class.
-     * To set multiple options, simply add them together:
-     * <p><code>ALLOW_2_SLASHES + NO_FRAGMENTS</code></p>
-     * enables both of those options.
-     */
-    public UrlValidator(final RegexValidator authorityValidator, final long options) {
-        this(null, authorityValidator, options);
-    }
-
-    /**
      * Customizable constructor. Validation behavior is modified by passing in options.
      * @param schemes the set of valid schemes. Ignored if the ALLOW_ALL_SCHEMES option is set.
      * @param authorityValidator Regular expression validator used to validate the authority part
@@ -265,7 +280,7 @@
         if (domainValidator == null) {
             throw new IllegalArgumentException("DomainValidator must not be null");
         }
-        if (domainValidator.isAllowLocal() != ((options & ALLOW_LOCAL_URLS) > 0)){
+        if (domainValidator.isAllowLocal() != (options & ALLOW_LOCAL_URLS) > 0) {
             throw new IllegalArgumentException("DomainValidator disagrees with ALLOW_LOCAL_URLS setting");
         }
         this.domainValidator = domainValidator;
@@ -286,12 +301,55 @@
     }
 
     /**
+     * Returns the number of times the token appears in the target.
+     * @param token Token value to be counted.
+     * @param target Target value to count tokens in.
+     * @return the number of tokens.
+     */
+    protected int countToken(final String token, final String target) {
+        int tokenIndex = 0;
+        int count = 0;
+        while (tokenIndex != -1) {
+            tokenIndex = target.indexOf(token, tokenIndex);
+            if (tokenIndex > -1) {
+                tokenIndex++;
+                count++;
+            }
+        }
+        return count;
+    }
+
+    /**
+     * Tests whether the given flag is off.  If the flag is not a power of 2
+     * (ie. 3) this tests whether the combination of flags is off.
+     *
+     * @param flag Flag value to check.
+     *
+     * @return whether the specified flag value is off.
+     */
+    private boolean isOff(final long flag) {
+        return (options & flag) == 0;
+    }
+
+    /**
+     * Tests whether the given flag is on.  If the flag is not a power of 2
+     * (ie. 3) this tests whether the combination of flags is on.
+     *
+     * @param flag Flag value to check.
+     *
+     * @return whether the specified flag value is on.
+     */
+    private boolean isOn(final long flag) {
+        return (options & flag) > 0;
+    }
+
+    /**
      * <p>Checks if a field has a valid URL address.</p>
      *
      * Note that the method calls #isValidAuthority()
      * which checks that the domain is valid.
      *
-     * @param value The value validation is being performed on.  A <code>null</code>
+     * @param value The value validation is being performed on.  A {@code null}
      * value is considered invalid.
      * @return true if the URL is valid.
      */
@@ -314,7 +372,7 @@
         }
 
         final String authority = uri.getRawAuthority();
-        if ("file".equals(scheme) && (authority == null || authority.isEmpty())) {// Special case - file: allows an empty authority
+        if ("file".equals(scheme) && (authority == null || authority.isEmpty())) { // Special case - file: allows an empty authority
             return true; // this is a local file - nothing more to do here
         }
         if ("file".equals(scheme) && authority != null && authority.contains(":")) {
@@ -341,33 +399,8 @@
     }
 
     /**
-     * Validate scheme. If schemes[] was initialized to a non null,
-     * then only those schemes are allowed.
-     * Otherwise the default schemes are "http", "https", "ftp".
-     * Matching is case-blind.
-     * @param scheme The scheme to validate.  A <code>null</code> value is considered
-     * invalid.
-     * @return true if valid.
-     */
-    protected boolean isValidScheme(final String scheme) {
-        if (scheme == null) {
-            return false;
-        }
-
-        if (!SCHEME_PATTERN.matcher(scheme).matches()) {
-            return false;
-        }
-
-        if (isOff(ALLOW_ALL_SCHEMES) && !allowedSchemes.contains(scheme.toLowerCase(Locale.ENGLISH))) {
-            return false;
-        }
-
-        return true;
-    }
-
-    /**
      * Returns true if the authority is properly formatted.  An authority is the combination
-     * of hostname and port.  A <code>null</code> authority value is considered invalid.
+     * of hostname and port.  A {@code null} authority value is considered invalid.
      * Note: this implementation validates the domain unless a RegexValidator was provided.
      * If a RegexValidator was supplied and it matches, then the authority is regarded
      * as valid with no further checks, otherwise the method checks against the
@@ -396,9 +429,9 @@
         final String ipv6 = authorityMatcher.group(PARSE_AUTHORITY_IPV6);
         if (ipv6 != null) {
             final InetAddressValidator inetAddressValidator = InetAddressValidator.getInstance();
-                if (!inetAddressValidator.isValidInet6Address(ipv6)) {
-                    return false;
-                }
+            if (!inetAddressValidator.isValidInet6Address(ipv6)) {
+                return false;
+            }
         } else {
             final String hostLocation = authorityMatcher.group(PARSE_AUTHORITY_HOST_IP);
             // check if authority is hostname or IP address:
@@ -425,7 +458,7 @@
         }
 
         final String extra = authorityMatcher.group(PARSE_AUTHORITY_EXTRA);
-        if (extra != null && !extra.trim().isEmpty()){
+        if (extra != null && !extra.trim().isEmpty()) {
             return false;
         }
 
@@ -433,7 +466,20 @@
     }
 
     /**
-     * Returns true if the path is valid.  A <code>null</code> value is considered invalid.
+     * Returns true if the given fragment is null or fragments are allowed.
+     * @param fragment Fragment value to validate.
+     * @return true if fragment is valid.
+     */
+    protected boolean isValidFragment(final String fragment) {
+        if (fragment == null) {
+            return true;
+        }
+
+        return isOff(NO_FRAGMENTS);
+    }
+
+    /**
+     * Returns true if the path is valid.  A {@code null} value is considered invalid.
      * @param path Path value to validate.
      * @return true if path is valid.
      */
@@ -459,7 +505,7 @@
         }
 
         final int slash2Count = countToken("//", path);
-        if (isOff(ALLOW_2_SLASHES) && (slash2Count > 0)) {
+        if (isOff(ALLOW_2_SLASHES) && slash2Count > 0) {
             return false;
         }
 
@@ -480,72 +526,28 @@
     }
 
     /**
-     * Returns true if the given fragment is null or fragments are allowed.
-     * @param fragment Fragment value to validate.
-     * @return true if fragment is valid.
+     * Validate scheme. If schemes[] was initialized to a non null,
+     * then only those schemes are allowed.
+     * Otherwise the default schemes are "http", "https", "ftp".
+     * Matching is case-blind.
+     * @param scheme The scheme to validate.  A {@code null} value is considered
+     * invalid.
+     * @return true if valid.
      */
-    protected boolean isValidFragment(final String fragment) {
-        if (fragment == null) {
-            return true;
+    protected boolean isValidScheme(final String scheme) {
+        if (scheme == null) {
+            return false;
         }
 
-        return isOff(NO_FRAGMENTS);
-    }
-
-    /**
-     * Returns the number of times the token appears in the target.
-     * @param token Token value to be counted.
-     * @param target Target value to count tokens in.
-     * @return the number of tokens.
-     */
-    protected int countToken(final String token, final String target) {
-        int tokenIndex = 0;
-        int count = 0;
-        while (tokenIndex != -1) {
-            tokenIndex = target.indexOf(token, tokenIndex);
-            if (tokenIndex > -1) {
-                tokenIndex++;
-                count++;
-            }
+        if (!SCHEME_PATTERN.matcher(scheme).matches()) {
+            return false;
         }
-        return count;
-    }
 
-    /**
-     * Tests whether the given flag is on.  If the flag is not a power of 2
-     * (ie. 3) this tests whether the combination of flags is on.
-     *
-     * @param flag Flag value to check.
-     *
-     * @return whether the specified flag value is on.
-     */
-    private boolean isOn(final long flag) {
-        return (options & flag) > 0;
-    }
+        if (isOff(ALLOW_ALL_SCHEMES) && !allowedSchemes.contains(scheme.toLowerCase(Locale.ENGLISH))) {
+            return false;
+        }
 
-    /**
-     * Tests whether the given flag is on.  If the flag is not a power of 2
-     * (e.g. 3) this tests whether the combination of flags is on.
-     *
-     * @param flag Flag value to check.
-     * @param options what to check
-     *
-     * @return whether the specified flag value is on.
-     */
-    private static boolean isOn(final long flag, final long options) {
-        return (options & flag) > 0;
-    }
-
-    /**
-     * Tests whether the given flag is off.  If the flag is not a power of 2
-     * (ie. 3) this tests whether the combination of flags is off.
-     *
-     * @param flag Flag value to check.
-     *
-     * @return whether the specified flag value is off.
-     */
-    private boolean isOff(final long flag) {
-        return (options & flag) == 0;
+        return true;
     }
 
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/ABANumberCheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/ABANumberCheckDigit.java
index ebaab4d..221d742 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/ABANumberCheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/ABANumberCheckDigit.java
@@ -37,7 +37,7 @@
  *
  * <p>
  * For further information see
- *  <a href="http://en.wikipedia.org/wiki/Routing_transit_number">Wikipedia -
+ *  <a href="https://en.wikipedia.org/wiki/Routing_transit_number">Wikipedia -
  *  Routing transit number</a>.
  * </p>
  *
@@ -50,14 +50,13 @@
     /** Singleton Routing Transit Number Check Digit instance */
     public static final CheckDigit ABAN_CHECK_DIGIT = new ABANumberCheckDigit();
 
-    /** weighting given to digits depending on their right position */
+    /** Weighting given to digits depending on their right position */
     private static final int[] POSITION_WEIGHT = {3, 1, 7};
 
     /**
-     * Construct a modulus 10 Check Digit routine for ABA Numbers.
+     * Constructs a modulus 10 Check Digit routine for ABA Numbers.
      */
     public ABANumberCheckDigit() {
-        super(10); // CHECKSTYLE IGNORE MagicNumber
     }
 
     /**
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/CUSIPCheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/CUSIPCheckDigit.java
index ba14ac8..b263223 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/CUSIPCheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/CUSIPCheckDigit.java
@@ -32,7 +32,7 @@
  * </p>
  *
  * <p>
- * See <a href="http://en.wikipedia.org/wiki/CUSIP">Wikipedia - CUSIP</a>
+ * See <a href="https://en.wikipedia.org/wiki/CUSIP">Wikipedia - CUSIP</a>
  * for more details.
  * </p>
  *
@@ -45,14 +45,13 @@
     /** Singleton CUSIP Check Digit instance */
     public static final CheckDigit CUSIP_CHECK_DIGIT = new CUSIPCheckDigit();
 
-    /** weighting given to digits depending on their right position */
+    /** Weighting given to digits depending on their right position */
     private static final int[] POSITION_WEIGHT = {2, 1};
 
     /**
-     * Construct an CUSIP Indetifier Check Digit routine.
+     * Constructs a CUSIP Identifier Check Digit routine.
      */
     public CUSIPCheckDigit() {
-        super(10); // CHECKSTYLE IGNORE MagicNumber
     }
 
     /**
@@ -62,7 +61,7 @@
      * @param leftPos The position of the character in the code, counting from left to right
      * @param rightPos The position of the character in the code, counting from right to left
      * @return The integer value of the character
-     * @throws CheckDigitException if character is not alphanumeric
+     * @throws CheckDigitException if the character is not alphanumeric
      */
     @Override
     protected int toInt(final char character, final int leftPos, final int rightPos)
@@ -87,13 +86,13 @@
      *
      * @param charValue The numeric value of the character.
      * @param leftPos The position of the character in the code, counting from left to right
-     * @param rightPos The positionof the character in the code, counting from right to left
+     * @param rightPos The position of the character in the code, counting from right to left
      * @return The weighted value of the character.
      */
     @Override
     protected int weightedValue(final int charValue, final int leftPos, final int rightPos) {
         final int weight = POSITION_WEIGHT[rightPos % 2];
-        final int weightedValue = (charValue * weight);
+        final int weightedValue = charValue * weight;
         return ModulusCheckDigit.sumDigits(weightedValue);
     }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/CheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/CheckDigit.java
index f51d609..7a4ff79 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/CheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/CheckDigit.java
@@ -64,8 +64,8 @@
      * Validates the check digit for the code.

      *

      * @param code The code to validate, the string must include the check digit.

-     * @return <code>true</code> if the check digit is valid, otherwise

-     * <code>false</code>.

+     * @return {@code true} if the check digit is valid, otherwise

+     * {@code false}.

      */

     boolean isValid(String code);

 

diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/CheckDigitException.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/CheckDigitException.java
index d8753a5..14a301e 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/CheckDigitException.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/CheckDigitException.java
@@ -26,13 +26,13 @@
     private static final long serialVersionUID = -3519894732624685477L;
 
     /**
-     * Construct an Exception with no message.
+     * Constructs an Exception with no message.
      */
     public CheckDigitException() {
     }
 
     /**
-     * Construct an Exception with a message.
+     * Constructs an Exception with a message.
      *
      * @param msg The error message.
      */
@@ -41,7 +41,7 @@
     }
 
     /**
-     * Construct an Exception with a message and
+     * Constructs an Exception with a message and
      * the underlying cause.
      *
      * @param msg The error message.
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/EAN13CheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/EAN13CheckDigit.java
index bbe6620..bb925d3 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/EAN13CheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/EAN13CheckDigit.java
@@ -27,13 +27,13 @@
  * For further information see:
  * <ul>
  *   <li>EAN-13 - see
- *       <a href="http://en.wikipedia.org/wiki/European_Article_Number">Wikipedia -
+ *       <a href="https://en.wikipedia.org/wiki/European_Article_Number">Wikipedia -
  *       European Article Number</a>.</li>
  *   <li>UPC - see
- *       <a href="http://en.wikipedia.org/wiki/Universal_Product_Code">Wikipedia -
+ *       <a href="https://en.wikipedia.org/wiki/Universal_Product_Code">Wikipedia -
  *       Universal Product Code</a>.</li>
  *   <li>ISBN-13 - see
- *       <a href="http://en.wikipedia.org/wiki/ISBN">Wikipedia - International
+ *       <a href="https://en.wikipedia.org/wiki/ISBN">Wikipedia - International
  *       Standard Book Number (ISBN)</a>.</li>
  * </ul>
  *
@@ -46,14 +46,13 @@
     /** Singleton EAN-13 Check Digit instance */
     public static final CheckDigit EAN13_CHECK_DIGIT = new EAN13CheckDigit();
 
-    /** weighting given to digits depending on their right position */
+    /** Weighting given to digits depending on their right position */
     private static final int[] POSITION_WEIGHT = {3, 1};
 
     /**
-     * Construct a modulus 10 Check Digit routine for EAN/UPC.
+     * Constructs a modulus 10 Check Digit routine for EAN/UPC.
      */
     public EAN13CheckDigit() {
-        super(10);  // CHECKSTYLE IGNORE MagicNumber
     }
 
     /**
@@ -71,7 +70,6 @@
      */
     @Override
     protected int weightedValue(final int charValue, final int leftPos, final int rightPos) {
-        final int weight = POSITION_WEIGHT[rightPos % 2];
-        return charValue * weight;
+        return charValue * POSITION_WEIGHT[rightPos % 2];
     }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/IBANCheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/IBANCheckDigit.java
index 1f2a18f..073c61d 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/IBANCheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/IBANCheckDigit.java
@@ -34,7 +34,7 @@
  * Note: the class does not check the format of the IBAN number, only the check digits.
  * <p>
  * For further information see
- *  <a href="http://en.wikipedia.org/wiki/International_Bank_Account_Number">Wikipedia -
+ *  <a href="https://en.wikipedia.org/wiki/International_Bank_Account_Number">Wikipedia -
  *  IBAN number</a>.
  *
  * @since 1.4
@@ -55,35 +55,12 @@
     private static final long MODULUS = 97;
 
     /**
-     * Construct Check Digit routine for IBAN Numbers.
+     * Constructs Check Digit routine for IBAN Numbers.
      */
     public IBANCheckDigit() {
     }
 
     /**
-     * Validate the check digit of an IBAN code.
-     *
-     * @param code The code to validate
-     * @return <code>true</code> if the check digit is valid, otherwise
-     * <code>false</code>
-     */
-    @Override
-    public boolean isValid(final String code) {
-        if (code == null || code.length() < MIN_CODE_LEN) {
-            return false;
-        }
-        final String check = code.substring(2, 4); // CHECKSTYLE IGNORE MagicNumber
-        if ("00".equals(check) || "01".equals(check) || "99".equals(check)) {
-            return false;
-        }
-        try {
-            return calculateModulus(code) == 1;
-        } catch (final CheckDigitException ex) {
-            return false;
-        }
-    }
-
-    /**
      * Calculate the <i>Check Digit</i> for an IBAN code.
      * <p>
      * <b>Note:</b> The check digit is the third and fourth
@@ -124,10 +101,33 @@
             }
             total = (charValue > 9 ? total * 100 : total * 10) + charValue; // CHECKSTYLE IGNORE MagicNumber
             if (total > MAX) {
-                total = total % MODULUS;
+                total %= MODULUS;
             }
         }
         return (int) (total % MODULUS);
     }
 
+    /**
+     * Validate the check digit of an IBAN code.
+     *
+     * @param code The code to validate
+     * @return {@code true} if the check digit is valid, otherwise
+     * {@code false}
+     */
+    @Override
+    public boolean isValid(final String code) {
+        if (code == null || code.length() < MIN_CODE_LEN) {
+            return false;
+        }
+        final String check = code.substring(2, 4); // CHECKSTYLE IGNORE MagicNumber
+        if ("00".equals(check) || "01".equals(check) || "99".equals(check)) {
+            return false;
+        }
+        try {
+            return calculateModulus(code) == 1;
+        } catch (final CheckDigitException ex) {
+            return false;
+        }
+    }
+
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/ISBN10CheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/ISBN10CheckDigit.java
index e3ae689..87dc1c3 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/ISBN10CheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/ISBN10CheckDigit.java
@@ -33,7 +33,7 @@
  * <p>
  * For further information see:
  * <ul>
- *   <li><a href="http://en.wikipedia.org/wiki/ISBN">Wikipedia - International
+ *   <li><a href="https://en.wikipedia.org/wiki/ISBN">Wikipedia - International
  *       Standard Book Number (ISBN)</a>.</li>
  *   <li><a href="http://www.isbn.org/standards/home/isbn/transition.asp">ISBN-13
  *       Transition details</a>.</li>
@@ -49,27 +49,28 @@
     public static final CheckDigit ISBN10_CHECK_DIGIT = new ISBN10CheckDigit();
 
     /**
-     * Construct a modulus 11 Check Digit routine for ISBN-10.
+     * Constructs a modulus 11 Check Digit routine for ISBN-10.
      */
     public ISBN10CheckDigit() {
-        super(11);  // CHECKSTYLE IGNORE MagicNumber
+        super(MODULUS_11);
     }
 
     /**
-     * Calculates the <i>weighted</i> value of a character in the
-     * code at a specified position.
+     * <p>Convert an integer value to a character at a specified position.</p>
      *
-     * <p>For ISBN-10 (from right to left) digits are weighted
-     * by their position.</p>
+     * <p>Value '10' for position 1 (check digit) converted to 'X'.</p>
      *
-     * @param charValue The numeric value of the character.
-     * @param leftPos The position of the character in the code, counting from left to right
-     * @param rightPos The positionof the character in the code, counting from right to left
-     * @return The weighted value of the character.
+     * @param charValue The integer value of the character.
+     * @return The converted character.
+     * @throws CheckDigitException if an error occurs.
      */
     @Override
-    protected int weightedValue(final int charValue, final int leftPos, final int rightPos) {
-        return charValue * rightPos;
+    protected String toCheckDigit(final int charValue)
+            throws CheckDigitException {
+        if (charValue == 10) {  // CHECKSTYLE IGNORE MagicNumber
+            return "X";
+        }
+        return super.toCheckDigit(charValue);
     }
 
     /**
@@ -94,21 +95,20 @@
     }
 
     /**
-     * <p>Convert an integer value to a character at a specified position.</p>
+     * Calculates the <i>weighted</i> value of a character in the
+     * code at a specified position.
      *
-     * <p>Value '10' for position 1 (check digit) converted to 'X'.</p>
+     * <p>For ISBN-10 (from right to left) digits are weighted
+     * by their position.</p>
      *
-     * @param charValue The integer value of the character.
-     * @return The converted character.
-     * @throws CheckDigitException if an error occurs.
+     * @param charValue The numeric value of the character.
+     * @param leftPos The position of the character in the code, counting from left to right
+     * @param rightPos The positionof the character in the code, counting from right to left
+     * @return The weighted value of the character.
      */
     @Override
-    protected String toCheckDigit(final int charValue)
-            throws CheckDigitException {
-        if (charValue == 10) {  // CHECKSTYLE IGNORE MagicNumber
-            return "X";
-        }
-        return super.toCheckDigit(charValue);
+    protected int weightedValue(final int charValue, final int leftPos, final int rightPos) {
+        return charValue * rightPos;
     }
 
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/ISBNCheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/ISBNCheckDigit.java
index c325adb..4bf6dbe 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/ISBNCheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/ISBNCheckDigit.java
@@ -44,7 +44,7 @@
     public static final CheckDigit ISBN13_CHECK_DIGIT = EAN13CheckDigit.EAN13_CHECK_DIGIT;
 
     /** Singleton combined ISBN-10 / ISBN-13 Check Digit instance */
-    public static final CheckDigit ISBN_CHECK_DIGIT   = new ISBNCheckDigit();
+    public static final CheckDigit ISBN_CHECK_DIGIT = new ISBNCheckDigit();
 
     /**
      * Calculate an ISBN-10 or ISBN-13 check digit, depending
@@ -86,9 +86,9 @@
      *
      * @param code The ISBN code to validate (should have a length of
      * 10 or 13)
-     * @return <code>true</code> if the code has a length of 10 and is
+     * @return {@code true} if the code has a length of 10 and is
      * a valid ISBN-10 check digit or the code has a length of 13 and is
-     * a valid ISBN-13 check digit - otherwise <code>false</code>.
+     * a valid ISBN-13 check digit - otherwise {@code false}.
      */
     @Override
     public boolean isValid(final String code) {
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/ISINCheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/ISINCheckDigit.java
index 2d7fd81..77edac3 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/ISINCheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/ISINCheckDigit.java
@@ -32,7 +32,7 @@
  * </p>
  *
  * <p>
- * See <a href="http://en.wikipedia.org/wiki/ISIN">Wikipedia - ISIN</a>
+ * See <a href="https://en.wikipedia.org/wiki/ISIN">Wikipedia - ISIN</a>
  * for more details.
  * </p>
  *
@@ -47,14 +47,13 @@
     /** Singleton ISIN Check Digit instance */
     public static final CheckDigit ISIN_CHECK_DIGIT = new ISINCheckDigit();
 
-    /** weighting given to digits depending on their right position */
+    /** Weighting given to digits depending on their right position */
     private static final int[] POSITION_WEIGHT = {2, 1};
 
     /**
-     * Construct an ISIN Indetifier Check Digit routine.
+     * Constructs an ISIN Identifier Check Digit routine.
      */
     public ISINCheckDigit() {
-        super(10); // CHECKSTYLE IGNORE MagicNumber
     }
 
     /**
@@ -68,21 +67,20 @@
      */
     @Override
     protected int calculateModulus(final String code, final boolean includesCheckDigit) throws CheckDigitException {
-        final StringBuilder transformed = new  StringBuilder(code.length() * 2); // CHECKSTYLE IGNORE MagicNumber
+        final StringBuilder transformed = new StringBuilder(code.length() * 2); // CHECKSTYLE IGNORE MagicNumber
         if (includesCheckDigit) {
-            final char checkDigit = code.charAt(code.length()-1); // fetch the last character
-            if (!Character.isDigit(checkDigit)){
-                throw new CheckDigitException("Invalid checkdigit["+ checkDigit+ "] in " + code);
+            final char checkDigit = code.charAt(code.length() - 1); // fetch the last character
+            if (!Character.isDigit(checkDigit)) {
+                throw new CheckDigitException("Invalid checkdigit[" + checkDigit + "] in " + code);
             }
         }
         for (int i = 0; i < code.length(); i++) {
             final int charValue = Character.getNumericValue(code.charAt(i));
             if (charValue < 0 || charValue > MAX_ALPHANUMERIC_VALUE) {
-                throw new CheckDigitException("Invalid Character[" +
-                        (i + 1) + "] = '" + charValue + "'");
+                throw new CheckDigitException("Invalid Character[" + (i + 1) + "] = '" + charValue + "'");
             }
-             // this converts alphanumerics to two digits
-             // so there is no need to overload toInt()
+            // this converts alphanumerics to two digits
+            // so there is no need to overload toInt()
             transformed.append(charValue);
         }
         return super.calculateModulus(transformed.toString(), includesCheckDigit);
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/ISSNCheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/ISSNCheckDigit.java
index dc0e19c..df58d02 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/ISSNCheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/ISSNCheckDigit.java
@@ -48,22 +48,16 @@
  */
 public final class ISSNCheckDigit extends ModulusCheckDigit {
 
-
     private static final long serialVersionUID = 1L;
 
     /** Singleton ISSN Check Digit instance */
     public static final CheckDigit ISSN_CHECK_DIGIT = new ISSNCheckDigit();
 
     /**
-     * Creates the instance using a checkdigit modulus of 11
+     * Creates the instance using a checkdigit modulus of 11.
      */
     public ISSNCheckDigit() {
-        super(11); // CHECKSTYLE IGNORE MagicNumber
-    }
-
-    @Override
-    protected int weightedValue(final int charValue, final int leftPos, final int rightPos) throws CheckDigitException {
-        return charValue * (9 - leftPos); // CHECKSTYLE IGNORE MagicNumber
+        super(MODULUS_11);
     }
 
     @Override
@@ -82,4 +76,9 @@
         }
         return super.toInt(character, leftPos, rightPos);
     }
+
+    @Override
+    protected int weightedValue(final int charValue, final int leftPos, final int rightPos) throws CheckDigitException {
+        return charValue * (9 - leftPos); // CHECKSTYLE IGNORE MagicNumber
+    }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/LuhnCheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/LuhnCheckDigit.java
index 41ed02c..e94c919 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/LuhnCheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/LuhnCheckDigit.java
@@ -21,8 +21,8 @@
  *
  * Luhn check digits are used, for example, by:
  * <ul>
- *    <li><a href="http://en.wikipedia.org/wiki/Credit_card">Credit Card Numbers</a></li>
- *    <li><a href="http://en.wikipedia.org/wiki/IMEI">IMEI Numbers</a> - International
+ *    <li><a href="https://en.wikipedia.org/wiki/Credit_card">Credit Card Numbers</a></li>
+ *    <li><a href="https://en.wikipedia.org/wiki/IMEI">IMEI Numbers</a> - International
  *        Mobile Equipment Identity Numbers</li>
  * </ul>
  * Check digit calculation is based on <i>modulus 10</i> with digits in
@@ -30,7 +30,7 @@
  * position digits being weighted 2 (weighted values greater than 9 have 9 subtracted).
  *
  * <p>
- * See <a href="http://en.wikipedia.org/wiki/Luhn_algorithm">Wikipedia</a>
+ * See <a href="https://en.wikipedia.org/wiki/Luhn_algorithm">Wikipedia</a>
  * for more details.
  * </p>
  *
@@ -43,14 +43,13 @@
     /** Singleton Luhn Check Digit instance */
     public static final CheckDigit LUHN_CHECK_DIGIT = new LuhnCheckDigit();
 
-    /** weighting given to digits depending on their right position */
+    /** Weighting given to digits depending on their right position */
     private static final int[] POSITION_WEIGHT = {2, 1};
 
     /**
-     * Construct a modulus 10 Luhn Check Digit routine.
+     * Constructs a modulus 10 Luhn Check Digit routine.
      */
     public LuhnCheckDigit() {
-        super(10); // CHECKSTYLE IGNORE MagicNumber
     }
 
     /**
@@ -70,6 +69,6 @@
     protected int weightedValue(final int charValue, final int leftPos, final int rightPos) {
         final int weight = POSITION_WEIGHT[rightPos % 2]; // CHECKSTYLE IGNORE MagicNumber
         final int weightedValue = charValue * weight;
-        return weightedValue > 9 ? (weightedValue - 9) : weightedValue; // CHECKSTYLE IGNORE MagicNumber
+        return weightedValue > 9 ? weightedValue - 9 : weightedValue; // CHECKSTYLE IGNORE MagicNumber
     }
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/ModulusCheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/ModulusCheckDigit.java
index 0d8dcdf..ba994ca 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/ModulusCheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/ModulusCheckDigit.java
@@ -21,27 +21,51 @@
 /**
  * Abstract <b>Modulus</b> Check digit calculation/validation.
  * <p>
- * Provides a <i>base</i> class for building <i>modulus</i> Check
- * Digit routines.
+ * Provides a <i>base</i> class for building <i>modulus</i> Check Digit routines.
+ * </p>
  * <p>
- * This implementation only handles <i>single-digit numeric</i> codes, such as
- * <b>EAN-13</b>. For <i>alphanumeric</i> codes such as <b>EAN-128</b> you
- * will need to implement/override the <code>toInt()</code> and
- * <code>toChar()</code> methods.
- * <p>
+ * This implementation only handles <i>single-digit numeric</i> codes, such as <b>EAN-13</b>. For <i>alphanumeric</i> codes such as <b>EAN-128</b> you will need
+ * to implement/override the <code>toInt()</code> and <code>toChar()</code> methods.
+ * </p>
  *
  * @since 1.4
  */
 public abstract class ModulusCheckDigit implements CheckDigit, Serializable {
 
+    static final int MODULUS_10 = 10;
+    static final int MODULUS_11 = 11;
     private static final long serialVersionUID = 2948962251251528941L;
 
-    // N.B. The modulus can be > 10 provided that the implementing class overrides toCheckDigit and toInt
-    // (for example as in ISBN10CheckDigit)
+    /**
+     * Add together the individual digits in a number.
+     *
+     * @param number The number whose digits are to be added
+     * @return The sum of the digits
+     */
+    public static int sumDigits(final int number) {
+        int total = 0;
+        int todo = number;
+        while (todo > 0) {
+            total += todo % 10; // CHECKSTYLE IGNORE MagicNumber
+            todo /= 10; // CHECKSTYLE IGNORE MagicNumber
+        }
+        return total;
+    }
+
+    /**
+     * The modulus can be greater than 10 provided that the implementing class overrides toCheckDigit and toInt (for example as in ISBN10CheckDigit).
+     */
     private final int modulus;
 
     /**
-     * Construct a {@link CheckDigit} routine for a specified modulus.
+     * Constructs a modulus 10 {@link CheckDigit} routine for a specified modulus.
+     */
+    ModulusCheckDigit() {
+        this(MODULUS_10);
+    }
+
+    /**
+     * Constructs a {@link CheckDigit} routine for a specified modulus.
      *
      * @param modulus The modulus value to use for the check digit calculation
      */
@@ -50,35 +74,6 @@
     }
 
     /**
-     * Return the modulus value this check digit routine is based on.
-     *
-     * @return The modulus value this check digit routine is based on
-     */
-    public int getModulus() {
-        return modulus;
-    }
-
-    /**
-     * Validate a modulus check digit for a code.
-     *
-     * @param code The code to validate
-     * @return <code>true</code> if the check digit is valid, otherwise
-     * <code>false</code>
-     */
-    @Override
-    public boolean isValid(final String code) {
-        if (code == null || code.isEmpty()) {
-            return false;
-        }
-        try {
-            final int modulusResult = calculateModulus(code, true);
-            return (modulusResult == 0);
-        } catch (final CheckDigitException  ex) {
-            return false;
-        }
-    }
-
-    /**
      * Calculate a modulus <i>Check Digit</i> for a code which does not yet have one.
      *
      * @param code The code for which to calculate the Check Digit;
@@ -109,7 +104,7 @@
         int total = 0;
         for (int i = 0; i < code.length(); i++) {
             final int lth = code.length() + (includesCheckDigit ? 0 : 1);
-            final int leftPos  = i + 1;
+            final int leftPos = i + 1;
             final int rightPos = lth - i;
             final int charValue = toInt(code.charAt(i), leftPos, rightPos);
             total += weightedValue(charValue, leftPos, rightPos);
@@ -121,46 +116,32 @@
     }
 
     /**
-     * Calculates the <i>weighted</i> value of a character in the
-     * code at a specified position.
-     * <p>
-     * Some modulus routines weight the value of a character
-     * depending on its position in the code (e.g. ISBN-10), while
-     * others use different weighting factors for odd/even positions
-     * (e.g. EAN or Luhn). Implement the appropriate mechanism
-     * required by overriding this method.
+     * Gets the modulus value this check digit routine is based on.
      *
-     * @param charValue The numeric value of the character
-     * @param leftPos The position of the character in the code, counting from left to right
-     * @param rightPos The positionof the character in the code, counting from right to left
-     * @return The weighted value of the character
-     * @throws CheckDigitException if an error occurs calculating
-     * the weighted value
+     * @return The modulus value this check digit routine is based on
      */
-    protected abstract int weightedValue(int charValue, int leftPos, int rightPos)
-            throws CheckDigitException;
-
+    public int getModulus() {
+        return modulus;
+    }
 
     /**
-     * Convert a character at a specified position to an integer value.
-     * <p>
-     * <b>Note:</b> this implementation only handlers numeric values
-     * For non-numeric characters, override this method to provide
-     * character--&gt;integer conversion.
+     * Validate a modulus check digit for a code.
      *
-     * @param character The character to convert
-     * @param leftPos The position of the character in the code, counting from left to right (for identifiying the position in the string)
-     * @param rightPos The position of the character in the code, counting from right to left (not used here)
-     * @return The integer value of the character
-     * @throws CheckDigitException if character is non-numeric
+     * @param code The code to validate
+     * @return {@code true} if the check digit is valid, otherwise
+     * {@code false}
      */
-    protected int toInt(final char character, final int leftPos, final int rightPos)
-            throws CheckDigitException {
-        if (Character.isDigit(character)) {
-            return Character.getNumericValue(character);
+    @Override
+    public boolean isValid(final String code) {
+        if (code == null || code.isEmpty()) {
+            return false;
         }
-        throw new CheckDigitException("Invalid Character[" +
-                leftPos + "] = '" + character + "'");
+        try {
+            final int modulusResult = calculateModulus(code, true);
+            return modulusResult == 0;
+        } catch (final CheckDigitException ex) {
+            return false;
+        }
     }
 
     /**
@@ -185,19 +166,45 @@
     }
 
     /**
-     * Add together the individual digits in a number.
+     * Convert a character at a specified position to an integer value.
+     * <p>
+     * <b>Note:</b> this implementation only handlers numeric values
+     * For non-numeric characters, override this method to provide
+     * character--&gt;integer conversion.
      *
-     * @param number The number whose digits are to be added
-     * @return The sum of the digits
+     * @param character The character to convert
+     * @param leftPos The position of the character in the code, counting from left to right (for identifiying the position in the string)
+     * @param rightPos The position of the character in the code, counting from right to left (not used here)
+     * @return The integer value of the character
+     * @throws CheckDigitException if character is non-numeric
      */
-    public static int sumDigits(final int number) {
-        int total = 0;
-        int todo = number;
-        while (todo > 0) {
-            total += todo % 10; // CHECKSTYLE IGNORE MagicNumber
-            todo  = todo / 10; // CHECKSTYLE IGNORE MagicNumber
+    protected int toInt(final char character, final int leftPos, final int rightPos)
+            throws CheckDigitException {
+        if (Character.isDigit(character)) {
+            return Character.getNumericValue(character);
         }
-        return total;
+        throw new CheckDigitException("Invalid Character[" +
+                leftPos + "] = '" + character + "'");
     }
 
+    /**
+     * Calculates the <i>weighted</i> value of a character in the
+     * code at a specified position.
+     * <p>
+     * Some modulus routines weight the value of a character
+     * depending on its position in the code (e.g. ISBN-10), while
+     * others use different weighting factors for odd/even positions
+     * (e.g. EAN or Luhn). Implement the appropriate mechanism
+     * required by overriding this method.
+     *
+     * @param charValue The numeric value of the character
+     * @param leftPos The position of the character in the code, counting from left to right
+     * @param rightPos The positionof the character in the code, counting from right to left
+     * @return The weighted value of the character
+     * @throws CheckDigitException if an error occurs calculating
+     * the weighted value
+     */
+    protected abstract int weightedValue(int charValue, int leftPos, int rightPos)
+            throws CheckDigitException;
+
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/ModulusTenCheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/ModulusTenCheckDigit.java
index 3f7d43a..fea5faa 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/ModulusTenCheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/ModulusTenCheckDigit.java
@@ -114,12 +114,23 @@
 

     private static final long serialVersionUID = -3752929983453368497L;

 

+    /**

+     * The weighted values to apply based on the character position

+     */

     private final int[] postitionWeight;

+

+    /**

+     * {@code true} if use positionWeights from right to left

+     */

     private final boolean useRightPos;

+

+    /**

+     * {@code true} if sum the digits of the weighted value

+     */

     private final boolean sumWeightedDigits;

 

     /**

-     * Construct a modulus 10 Check Digit routine with the specified weighting

+     * Constructs a modulus 10 Check Digit routine with the specified weighting

      * from left to right.

      *

      * @param postitionWeight the weighted values to apply based on the

@@ -130,12 +141,12 @@
     }

 

     /**

-     * Construct a modulus 10 Check Digit routine with the specified weighting,

+     * Constructs a modulus 10 Check Digit routine with the specified weighting,

      * indicating whether its from the left or right.

      *

      * @param postitionWeight the weighted values to apply based on the

      *            character position

-     * @param useRightPos <code>true</code> if use positionWeights from right to

+     * @param useRightPos {@code true} if use positionWeights from right to

      *            left

      */

     public ModulusTenCheckDigit(final int[] postitionWeight, final boolean useRightPos) {

@@ -143,19 +154,18 @@
     }

 

     /**

-     * Construct a modulus 10 Check Digit routine with the specified weighting,

+     * Constructs a modulus 10 Check Digit routine with the specified weighting,

      * indicating whether its from the left or right and whether the weighted

      * digits should be summed.

      *

      * @param postitionWeight the weighted values to apply based on the

      *            character position

-     * @param useRightPos <code>true</code> if use positionWeights from right to

+     * @param useRightPos {@code true} if use positionWeights from right to

      *            left

-     * @param sumWeightedDigits <code>true</code> if sum the digits of the

+     * @param sumWeightedDigits {@code true} if sum the digits of the

      *            weighted value

      */

     public ModulusTenCheckDigit(final int[] postitionWeight, final boolean useRightPos, final boolean sumWeightedDigits) {

-        super(10); // CHECKSTYLE IGNORE MagicNumber

         this.postitionWeight = Arrays.copyOf(postitionWeight, postitionWeight.length);

         this.useRightPos = useRightPos;

         this.sumWeightedDigits = sumWeightedDigits;

@@ -167,8 +177,8 @@
      * Note: assumes last digit is the check digit

      *

      * @param code The code to validate

-     * @return <code>true</code> if the check digit is valid, otherwise

-     *         <code>false</code>

+     * @return {@code true} if the check digit is valid, otherwise

+     *         {@code false}

      */

     @Override

     public boolean isValid(final String code) {

@@ -207,6 +217,17 @@
     }

 

     /**

+     * Return a string representation of this implementation.

+     *

+     * @return a string representation

+     */

+    @Override

+    public String toString() {

+        return getClass().getSimpleName() + "[postitionWeight=" + Arrays.toString(postitionWeight) + ", useRightPos="

+                + useRightPos + ", sumWeightedDigits=" + sumWeightedDigits + "]";

+    }

+

+    /**

      * Calculates the <i>weighted</i> value of a character in the code at a

      * specified position.

      *

@@ -228,15 +249,4 @@
         return weightedValue;

     }

 

-    /**

-     * Return a string representation of this implementation.

-     *

-     * @return a string representation

-     */

-    @Override

-    public String toString() {

-        return getClass().getSimpleName() + "[postitionWeight=" + Arrays.toString(postitionWeight) + ", useRightPos="

-                + useRightPos + ", sumWeightedDigits=" + sumWeightedDigits + "]";

-    }

-

 }

diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/SedolCheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/SedolCheckDigit.java
index 9b29a8c..fc9726e 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/SedolCheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/SedolCheckDigit.java
@@ -32,7 +32,7 @@
  *     weighting:  1  3  1  7  3  9  1
  * </code></pre>
  * <p>
- * See <a href="http://en.wikipedia.org/wiki/SEDOL">Wikipedia - SEDOL</a>
+ * See <a href="https://en.wikipedia.org/wiki/SEDOL">Wikipedia - SEDOL</a>
  * for more details.
  * </p>
  *
@@ -47,14 +47,13 @@
     /** Singleton SEDOL check digit instance */
     public static final CheckDigit SEDOL_CHECK_DIGIT = new SedolCheckDigit();
 
-    /** weighting given to digits depending on their right position */
+    /** Weighting given to digits depending on their right position */
     private static final int[] POSITION_WEIGHT = {1, 3, 1, 7, 3, 9, 1};
 
     /**
-     * Construct a modulus 11 Check Digit routine for ISBN-10.
+     * Constructs a modulus 10 Check Digit routine for ISBN-10.
      */
     public SedolCheckDigit() {
-        super(10); // CHECKSTYLE IGNORE MagicNumber
     }
 
     /**
@@ -75,20 +74,6 @@
     }
 
     /**
-     * Calculates the <i>weighted</i> value of a character in the
-     * code at a specified position.
-     *
-     * @param charValue The numeric value of the character.
-     * @param leftPos The position of the character in the code, counting from left to right
-     * @param rightPos The positionof the character in the code, counting from right to left
-     * @return The weighted value of the character.
-     */
-    @Override
-    protected int weightedValue(final int charValue, final int leftPos, final int rightPos) {
-        return charValue * POSITION_WEIGHT[leftPos - 1];
-    }
-
-    /**
      * Convert a character at a specified position to an integer value.
      *
      * @param character The character to convert
@@ -110,4 +95,18 @@
         return charValue;
     }
 
+    /**
+     * Calculates the <i>weighted</i> value of a character in the
+     * code at a specified position.
+     *
+     * @param charValue The numeric value of the character.
+     * @param leftPos The position of the character in the code, counting from left to right
+     * @param rightPos The positionof the character in the code, counting from right to left
+     * @return The weighted value of the character.
+     */
+    @Override
+    protected int weightedValue(final int charValue, final int leftPos, final int rightPos) {
+        return charValue * POSITION_WEIGHT[leftPos - 1];
+    }
+
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/checkdigit/VerhoeffCheckDigit.java b/src/main/java/org/apache/commons/validator/routines/checkdigit/VerhoeffCheckDigit.java
index 27ccd9e..42fe541 100644
--- a/src/main/java/org/apache/commons/validator/routines/checkdigit/VerhoeffCheckDigit.java
+++ b/src/main/java/org/apache/commons/validator/routines/checkdigit/VerhoeffCheckDigit.java
@@ -22,10 +22,10 @@
  * <b>Verhoeff</b> (Dihedral) Check Digit calculation/validation.
  * <p>
  * Check digit calculation for numeric codes using a
- * <a href="http://en.wikipedia.org/wiki/Dihedral_group">Dihedral Group</a>
+ * <a href="https://en.wikipedia.org/wiki/Dihedral_group">Dihedral Group</a>
  * of order 10.
  * <p>
- * See <a href="http://en.wikipedia.org/wiki/Verhoeff_algorithm">Wikipedia
+ * See <a href="https://en.wikipedia.org/wiki/Verhoeff_algorithm">Wikipedia
  *  - Verhoeff algorithm</a> for more details.
  *
  * @since 1.4
@@ -39,50 +39,30 @@
 
     /** D - multiplication table */
     private static final int[][] D_TABLE = {
-        {0,  1,  2,  3,  4,  5,  6,  7,  8,  9},
-        {1,  2,  3,  4,  0,  6,  7,  8,  9,  5},
-        {2,  3,  4,  0,  1,  7,  8,  9,  5,  6},
-        {3,  4,  0,  1,  2,  8,  9,  5,  6,  7},
-        {4,  0,  1,  2,  3,  9,  5,  6,  7,  8},
-        {5,  9,  8,  7,  6,  0,  4,  3,  2,  1},
-        {6,  5,  9,  8,  7,  1,  0,  4,  3,  2},
-        {7,  6,  5,  9,  8,  2,  1,  0,  4,  3},
-        {8,  7,  6,  5,  9,  3,  2,  1,  0,  4},
-        {9,  8,  7,  6,  5,  4,  3,  2,  1,  0}};
+        {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+        {1, 2, 3, 4, 0, 6, 7, 8, 9, 5},
+        {2, 3, 4, 0, 1, 7, 8, 9, 5, 6},
+        {3, 4, 0, 1, 2, 8, 9, 5, 6, 7},
+        {4, 0, 1, 2, 3, 9, 5, 6, 7, 8},
+        {5, 9, 8, 7, 6, 0, 4, 3, 2, 1},
+        {6, 5, 9, 8, 7, 1, 0, 4, 3, 2},
+        {7, 6, 5, 9, 8, 2, 1, 0, 4, 3},
+        {8, 7, 6, 5, 9, 3, 2, 1, 0, 4},
+        {9, 8, 7, 6, 5, 4, 3, 2, 1, 0}};
 
     /** P - permutation table */
     private static final int[][] P_TABLE = {
-        {0,  1,  2,  3,  4,  5,  6,  7,  8,  9},
-        {1,  5,  7,  6,  2,  8,  3,  0,  9,  4},
-        {5,  8,  0,  3,  7,  9,  6,  1,  4,  2},
-        {8,  9,  1,  6,  0,  4,  3,  5,  2,  7},
-        {9,  4,  5,  3,  1,  2,  6,  8,  7,  0},
-        {4,  2,  8,  6,  5,  7,  3,  9,  0,  1},
-        {2,  7,  9,  3,  8,  0,  6,  4,  1,  5},
-        {7,  0,  4,  6,  9,  1,  3,  2,  5,  8}};
+        {0, 1, 2, 3, 4, 5, 6, 7, 8, 9},
+        {1, 5, 7, 6, 2, 8, 3, 0, 9, 4},
+        {5, 8, 0, 3, 7, 9, 6, 1, 4, 2},
+        {8, 9, 1, 6, 0, 4, 3, 5, 2, 7},
+        {9, 4, 5, 3, 1, 2, 6, 8, 7, 0},
+        {4, 2, 8, 6, 5, 7, 3, 9, 0, 1},
+        {2, 7, 9, 3, 8, 0, 6, 4, 1, 5},
+        {7, 0, 4, 6, 9, 1, 3, 2, 5, 8}};
 
-    /** inv: inverse table */
-    private static final int[] INV_TABLE = {0,  4,  3,  2,  1,  5,  6,  7,  8,  9};
-
-
-    /**
-     * Validate the Verhoeff <i>Check Digit</i> for a code.
-     *
-     * @param code The code to validate
-     * @return <code>true</code> if the check digit is valid,
-     * otherwise <code>false</code>
-     */
-    @Override
-    public boolean isValid(final String code) {
-        if (code == null || code.isEmpty()) {
-            return false;
-        }
-        try {
-            return (calculateChecksum(code, true) == 0);
-        } catch (final CheckDigitException e) {
-            return false;
-        }
-    }
+    /** Inverse table */
+    private static final int[] INV_TABLE = {0, 4, 3, 2, 1, 5, 6, 7, 8, 9};
 
     /**
      * Calculate a Verhoeff <i>Check Digit</i> for a code.
@@ -116,7 +96,7 @@
             final int num = Character.getNumericValue(code.charAt(idx));
             if (num < 0 || num > 9) { // CHECKSTYLE IGNORE MagicNumber
                 throw new CheckDigitException("Invalid Character[" +
-                        i + "] = '" + ((int)code.charAt(idx)) + "'");
+                        i + "] = '" + (int)code.charAt(idx) + "'");
             }
             final int pos = includesCheckDigit ? i : i + 1;
             checksum = D_TABLE[checksum][P_TABLE[pos % 8][num]]; // CHECKSTYLE IGNORE MagicNumber
@@ -124,4 +104,23 @@
         return checksum;
     }
 
+    /**
+     * Validate the Verhoeff <i>Check Digit</i> for a code.
+     *
+     * @param code The code to validate
+     * @return {@code true} if the check digit is valid,
+     * otherwise {@code false}
+     */
+    @Override
+    public boolean isValid(final String code) {
+        if (code == null || code.isEmpty()) {
+            return false;
+        }
+        try {
+            return calculateChecksum(code, true) == 0;
+        } catch (final CheckDigitException e) {
+            return false;
+        }
+    }
+
 }
diff --git a/src/main/java/org/apache/commons/validator/routines/package-info.java b/src/main/java/org/apache/commons/validator/routines/package-info.java
index 5a2becc..a2a31e5 100644
--- a/src/main/java/org/apache/commons/validator/routines/package-info.java
+++ b/src/main/java/org/apache/commons/validator/routines/package-info.java
@@ -150,7 +150,7 @@
  * // Validate/Convert the date using GMT
  * Date fooDate = validator.validate(fooString, "dd/MM/yyyy", GMT);
  * </pre>
- * <p>The following Time Zone <i>flavours</i> of the Validation/Conversion methods
+ * <p>The following Time Zone <i>flavors</i> of the Validation/Conversion methods
  * are provided:</p>
  * <ul>
  * <li><code>validate(<i>value</i>, TimeZone)</code></li>
@@ -406,16 +406,16 @@
  * by creating a new instance, which caches and re-uses compiled Patterns.
  * </p>
  * <ul>
- * <li><b>Method Flavours</b> - three <i>flavours</i> of validation metods are provided:</li>
+ * <li><b>Method Flavours</b> - three <i>flavors</i> of validation metods are provided:</li>
  * <li>
  * <ul>
  * <li><code>isValid()</code> methods return true/false to indicate
  * whether validation was successful.</li>
  * <li><code>validate()</code> methods return a <code>String</code>
  * value of the matched <i>groups</i> aggregated together or
- * <code>null</code> if invalid.</li>
+ * {@code null} if invalid.</li>
  * <li><code>match()</code> methods return a <code>String</code> array
- * of the matched <i>groups</i> or <code>null</code> if invalid.</li>
+ * of the matched <i>groups</i> or {@code null} if invalid.</li>
  * </ul>
  * </li>
  * <li><b>Case Sensitivity</b> - matching can be done in either a <i>case
@@ -468,7 +468,7 @@
  * String[] groups = validator.match("abc-def");
  * </pre>
  * <p>See the
- * <a href="RegexValidator.html">RegexValidator</a> javadoc for a full list
+ * <a href="RegexValidator.html">RegexValidator</a> Javadoc for a full list
  * of the available constructors.
  * </p>
  * <a id="other.checkdigit"></a>
@@ -480,7 +480,7 @@
  * </p>
  * <ul>
  * <li><code>isValid(<i>code</i>)</code> - validates the check digit of a code,
- * returning <code>true</code> or <code>false</code>.</li>
+ * returning {@code true} or {@code false}.</li>
  * <li><code>calculate(<i>code</i>)</code> - calulates the check digit for a code
  * returning the check digit character.</li>
  * </ul>
@@ -605,7 +605,7 @@
  * <ul>
  * <li><code>isValid(<i>value</i>)</code> - returns a boolean</li>
  * <li><code>validate(<i>value</i>)</code> - returns a reformatted ISBN code
- * (converts ISBN-10 to ISBN-13 if the <i>convert</i> option is <code>true</code>).</li>
+ * (converts ISBN-10 to ISBN-13 if the <i>convert</i> option is {@code true}).</li>
  * </ul>
  * </li>
  * </ul>
diff --git a/src/main/java/org/apache/commons/validator/util/Flags.java b/src/main/java/org/apache/commons/validator/util/Flags.java
index a04d16c..e29a998 100644
--- a/src/main/java/org/apache/commons/validator/util/Flags.java
+++ b/src/main/java/org/apache/commons/validator/util/Flags.java
@@ -61,6 +61,48 @@
     }
 
     /**
+     * Turn off all flags.  This is a synonym for <code>turnOffAll()</code>.
+     * @since 1.1.1
+     */
+    public void clear() {
+        this.flags = 0;
+    }
+
+    /**
+     * Clone this Flags object.
+     *
+     * @return a copy of this object.
+     * @see Object#clone()
+     */
+    @Override
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (final CloneNotSupportedException e) {
+            throw new UnsupportedOperationException("Couldn't clone Flags object.", e);
+        }
+    }
+
+    /**
+     * Tests if two Flags objects are in the same state.
+     * @param obj object being tested
+     * @see Object#equals(Object)
+     *
+     * @return whether the objects are equal.
+     */
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (!(obj instanceof Flags)) {
+            return false;
+        }
+        final Flags other = (Flags) obj;
+        return flags == other.flags;
+    }
+
+    /**
      * Returns the current flags.
      *
      * @return collection of boolean flags represented.
@@ -70,15 +112,14 @@
     }
 
     /**
-     * Tests whether the given flag is on.  If the flag is not a power of 2
-     * (ie. 3) this tests whether the combination of flags is on.
+     * The hash code is based on the current state of the flags.
+     * @see Object#hashCode()
      *
-     * @param flag Flag value to check.
-     *
-     * @return whether the specified flag value is on.
+     * @return the hash code for this object.
      */
-    public boolean isOn(final long flag) {
-        return (this.flags & flag) == flag;
+    @Override
+    public int hashCode() {
+        return (int) this.flags;
     }
 
     /**
@@ -94,13 +135,31 @@
     }
 
     /**
-     * Turns on the given flag.  If the flag is not a power of 2 (ie. 3) this
-     * turns on multiple flags.
+     * Tests whether the given flag is on.  If the flag is not a power of 2
+     * (ie. 3) this tests whether the combination of flags is on.
      *
-     * @param flag Flag value to turn on.
+     * @param flag Flag value to check.
+     *
+     * @return whether the specified flag value is on.
      */
-    public void turnOn(final long flag) {
-        this.flags |= flag;
+    public boolean isOn(final long flag) {
+        return (this.flags & flag) == flag;
+    }
+
+    /**
+     * Returns a 64 length String with the first flag on the right and the
+     * 64th flag on the left.  A 1 indicates the flag is on, a 0 means it's
+     * off.
+     *
+     * @return string representation of this object.
+     */
+    @Override
+    public String toString() {
+        final StringBuilder bin = new StringBuilder(Long.toBinaryString(this.flags));
+        for (int i = 64 - bin.length(); i > 0; i--) { // CHECKSTYLE IGNORE MagicNumber
+            bin.insert(0, "0");
+        }
+        return bin.toString();
     }
 
     /**
@@ -121,11 +180,13 @@
     }
 
     /**
-     * Turn off all flags.  This is a synonym for <code>turnOffAll()</code>.
-     * @since 1.1.1
+     * Turns on the given flag.  If the flag is not a power of 2 (ie. 3) this
+     * turns on multiple flags.
+     *
+     * @param flag Flag value to turn on.
      */
-    public void clear() {
-        this.flags = 0;
+    public void turnOn(final long flag) {
+        this.flags |= flag;
     }
 
     /**
@@ -135,68 +196,4 @@
         this.flags = 0xFFFFFFFFFFFFFFFFL;
     }
 
-    /**
-     * Clone this Flags object.
-     *
-     * @return a copy of this object.
-     * @see Object#clone()
-     */
-    @Override
-    public Object clone() {
-        try {
-            return super.clone();
-        } catch(final CloneNotSupportedException e) {
-            throw new RuntimeException("Couldn't clone Flags object.");
-        }
-    }
-
-    /**
-     * Tests if two Flags objects are in the same state.
-     * @param obj object being tested
-     * @see Object#equals(Object)
-     *
-     * @return whether the objects are equal.
-     */
-    @Override
-    public boolean equals(final Object obj) {
-        if (!(obj instanceof Flags)) {
-            return false;
-        }
-
-        if (obj == this) {
-            return true;
-        }
-
-        final Flags f = (Flags) obj;
-
-        return this.flags == f.flags;
-    }
-
-    /**
-     * The hash code is based on the current state of the flags.
-     * @see Object#hashCode()
-     *
-     * @return the hash code for this object.
-     */
-    @Override
-    public int hashCode() {
-        return (int) this.flags;
-    }
-
-    /**
-     * Returns a 64 length String with the first flag on the right and the
-     * 64th flag on the left.  A 1 indicates the flag is on, a 0 means it's
-     * off.
-     *
-     * @return string representation of this object.
-     */
-    @Override
-    public String toString() {
-        final StringBuilder bin = new StringBuilder(Long.toBinaryString(this.flags));
-        for (int i = 64 - bin.length(); i > 0; i--) { // CHECKSTYLE IGNORE MagicNumber
-            bin.insert(0, "0");
-        }
-        return bin.toString();
-    }
-
 }
diff --git a/src/main/java/org/apache/commons/validator/util/ValidatorUtils.java b/src/main/java/org/apache/commons/validator/util/ValidatorUtils.java
index 751f214..552b3da 100644
--- a/src/main/java/org/apache/commons/validator/util/ValidatorUtils.java
+++ b/src/main/java/org/apache/commons/validator/util/ValidatorUtils.java
@@ -16,10 +16,11 @@
  */
 package org.apache.commons.validator.util;
 
-import java.lang.reflect.InvocationTargetException;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.Map;
+import java.util.Map.Entry;
 
 import org.apache.commons.beanutils.PropertyUtils;
 import org.apache.commons.collections.FastHashMap; // DEPRECATED
@@ -41,44 +42,63 @@
     private static final Log LOG = LogFactory.getLog(ValidatorUtils.class);
 
     /**
-     * <p>Replace part of a <code>String</code> with another value.</p>
+     * Makes a deep copy of a <code>FastHashMap</code> if the values
+     * are <code>Msg</code>, <code>Arg</code>,
+     * or <code>Var</code>.  Otherwise it is a shallow copy.
      *
-     * @param value <code>String</code> to perform the replacement on.
-     * @param key The name of the constant.
-     * @param replaceValue The value of the constant.
-     *
-     * @return The modified value.
+     * @param fastHashMap <code>FastHashMap</code> to copy.
+     * @return FastHashMap A copy of the <code>FastHashMap</code> that was
+     * passed in.
+     * @deprecated This method is not part of Validator's public API.  Validator
+     * will use it internally until FastHashMap references are removed.  Use
+     * copyMap() instead.
      */
-    public static String replace(String value, final String key, final String replaceValue) {
-
-        if (value == null || key == null || replaceValue == null) {
-            return value;
+    @Deprecated
+    public static FastHashMap copyFastHashMap(final FastHashMap fastHashMap) {
+        FastHashMap results = new FastHashMap();
+        @SuppressWarnings("unchecked") // FastHashMap is not generic
+        Iterator<Entry<String, ?>> iterator = fastHashMap.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Entry<String, ?> entry = iterator.next();
+            String key = entry.getKey();
+            Object value = entry.getValue();
+            if (value instanceof Msg) {
+                results.put(key, ((Msg) value).clone());
+            } else if (value instanceof Arg) {
+                results.put(key, ((Arg) value).clone());
+            } else if (value instanceof Var) {
+                results.put(key, ((Var) value).clone());
+            } else {
+                results.put(key, value);
+            }
         }
+        results.setFast(true);
+        return results;
+    }
 
-        final int pos = value.indexOf(key);
-
-        if (pos < 0) {
-            return value;
-        }
-
-        final int length = value.length();
-        final int start = pos;
-        final int end = pos + key.length();
-
-        if (length == key.length()) {
-            value = replaceValue;
-
-        } else if (end == length) {
-            value = value.substring(0, start) + replaceValue;
-
-        } else {
-            value =
-                    value.substring(0, start)
-                    + replaceValue
-                    + replace(value.substring(end), key, replaceValue);
-        }
-
-        return value;
+    /**
+     * Makes a deep copy of a <code>Map</code> if the values are
+     * <code>Msg</code>, <code>Arg</code>, or <code>Var</code>.  Otherwise,
+     * it is a shallow copy.
+     *
+     * @param map The source Map to copy.
+     *
+     * @return A copy of the <code>Map</code> that was passed in.
+     */
+    public static Map<String, Object> copyMap(final Map<String, Object> map) {
+        final Map<String, Object> results = new HashMap<>(map.size());
+        map.forEach((key, value) -> {
+            if (value instanceof Msg) {
+                results.put(key, ((Msg) value).clone());
+            } else if (value instanceof Arg) {
+                results.put(key, ((Arg) value).clone());
+            } else if (value instanceof Var) {
+                results.put(key, ((Var) value).clone());
+            } else {
+                results.put(key, value);
+            }
+        });
+        return results;
     }
 
     /**
@@ -86,7 +106,7 @@
      * <code>String</code>.  If the property is a <code>String[]</code> or
      * <code>Collection</code> and it is empty, an empty <code>String</code>
      * "" is returned.  Otherwise, property.toString() is returned.  This method
-     * may return <code>null</code> if there was an error retrieving the
+     * may return {@code null} if there was an error retrieving the
      * property.
      *
      * @param bean The bean object.
@@ -100,7 +120,7 @@
         try {
             value = PropertyUtils.getProperty(bean, property);
 
-        } catch(IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
+        } catch (final ReflectiveOperationException e) {
             LOG.error(e.getMessage(), e);
         }
 
@@ -121,60 +141,19 @@
     }
 
     /**
-     * Makes a deep copy of a <code>FastHashMap</code> if the values
-     * are <code>Msg</code>, <code>Arg</code>,
-     * or <code>Var</code>.  Otherwise it is a shallow copy.
+     * <p>Replace part of a <code>String</code> with another value.</p>
      *
-     * @param fastHashMap <code>FastHashMap</code> to copy.
-     * @return FastHashMap A copy of the <code>FastHashMap</code> that was
-     * passed in.
-     * @deprecated This method is not part of Validator's public API.  Validator
-     * will use it internally until FastHashMap references are removed.  Use
-     * copyMap() instead.
+     * @param value <code>String</code> to perform the replacement on.
+     * @param key The name of the constant.
+     * @param replaceValue The value of the constant.
+     *
+     * @return The modified value.
      */
-    @Deprecated
-    public static FastHashMap copyFastHashMap(final FastHashMap fastHashMap) {
-        final FastHashMap results = new FastHashMap();
-        @SuppressWarnings("unchecked") // FastHashMap is not generic
-        final HashMap<String, ?> map = fastHashMap;
-        map.forEach((key, value) -> {
-            if (value instanceof Msg) {
-                results.put(key, ((Msg) value).clone());
-            } else if (value instanceof Arg) {
-                results.put(key, ((Arg) value).clone());
-            } else if (value instanceof Var) {
-                results.put(key, ((Var) value).clone());
-            } else {
-                results.put(key, value);
-            }
-        });
-        results.setFast(true);
-        return results;
-    }
-
-    /**
-     * Makes a deep copy of a <code>Map</code> if the values are
-     * <code>Msg</code>, <code>Arg</code>, or <code>Var</code>.  Otherwise,
-     * it is a shallow copy.
-     *
-     * @param map The source Map to copy.
-     *
-     * @return A copy of the <code>Map</code> that was passed in.
-     */
-    public static Map<String, Object> copyMap(final Map<String, Object> map) {
-        final Map<String, Object> results = new HashMap<>();
-        map.forEach((key, value) -> {
-            if (value instanceof Msg) {
-                results.put(key, ((Msg) value).clone());
-            } else if (value instanceof Arg) {
-                results.put(key, ((Arg) value).clone());
-            } else if (value instanceof Var) {
-                results.put(key, ((Var) value).clone());
-            } else {
-                results.put(key, value);
-            }
-        });
-        return results;
+    public static String replace(final String value, final String key, final String replaceValue) {
+        if (value == null || key == null || replaceValue == null) {
+            return value;
+        }
+        return value.replace(key, replaceValue);
     }
 
 }
diff --git a/src/main/resources/org/apache/commons/validator/digester-rules.xml b/src/main/resources/org/apache/commons/validator/digester-rules.xml
index 50fde77..8647f79 100644
--- a/src/main/resources/org/apache/commons/validator/digester-rules.xml
+++ b/src/main/resources/org/apache/commons/validator/digester-rules.xml
@@ -19,8 +19,6 @@
 <!--
     digester-rules.xml defines the rules our Digester will use to transform 
     validation.xml files into Java objects.
-    
-    $Id$
 -->
 
 
diff --git a/src/main/resources/org/apache/commons/validator/resources/validator_1_0.dtd b/src/main/resources/org/apache/commons/validator/resources/validator_1_0.dtd
index 6dfb90b..b805751 100644
--- a/src/main/resources/org/apache/commons/validator/resources/validator_1_0.dtd
+++ b/src/main/resources/org/apache/commons/validator/resources/validator_1_0.dtd
@@ -25,7 +25,6 @@
      "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0//EN"
      "http://jakarta.apache.org/commons/dtds/validator_1_0.dtd">
 
-    $Id$
 -->
 
 
diff --git a/src/main/resources/org/apache/commons/validator/resources/validator_1_0_1.dtd b/src/main/resources/org/apache/commons/validator/resources/validator_1_0_1.dtd
index f521169..ea1b39e 100644
--- a/src/main/resources/org/apache/commons/validator/resources/validator_1_0_1.dtd
+++ b/src/main/resources/org/apache/commons/validator/resources/validator_1_0_1.dtd
@@ -25,7 +25,6 @@
      "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.0.1//EN"
      "http://jakarta.apache.org/commons/dtds/validator_1_0_1.dtd">
 
-    $Id$
 -->
 
 
diff --git a/src/main/resources/org/apache/commons/validator/resources/validator_1_1.dtd b/src/main/resources/org/apache/commons/validator/resources/validator_1_1.dtd
index 671e740..b015b38 100644
--- a/src/main/resources/org/apache/commons/validator/resources/validator_1_1.dtd
+++ b/src/main/resources/org/apache/commons/validator/resources/validator_1_1.dtd
@@ -25,7 +25,6 @@
      "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1//EN"
      "http://jakarta.apache.org/commons/dtds/validator_1_1.dtd">
 
-    $Id$
 -->
 
 
diff --git a/src/main/resources/org/apache/commons/validator/resources/validator_1_1_3.dtd b/src/main/resources/org/apache/commons/validator/resources/validator_1_1_3.dtd
index 8dce2b8..f7306d5 100644
--- a/src/main/resources/org/apache/commons/validator/resources/validator_1_1_3.dtd
+++ b/src/main/resources/org/apache/commons/validator/resources/validator_1_1_3.dtd
@@ -25,7 +25,6 @@
      "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.1.3//EN"
      "http://jakarta.apache.org/commons/dtds/validator_1_1_3.dtd">
 
-    $Id$
 -->
 
 
diff --git a/src/main/resources/org/apache/commons/validator/resources/validator_1_2_0.dtd b/src/main/resources/org/apache/commons/validator/resources/validator_1_2_0.dtd
index 58d5adc..a74bd4a 100644
--- a/src/main/resources/org/apache/commons/validator/resources/validator_1_2_0.dtd
+++ b/src/main/resources/org/apache/commons/validator/resources/validator_1_2_0.dtd
@@ -25,7 +25,6 @@
      "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.2.0//EN"
      "http://jakarta.apache.org/commons/dtds/validator_1_2_0.dtd">
 
-    $Id$
 -->
 
 
diff --git a/src/main/resources/org/apache/commons/validator/resources/validator_1_3_0.dtd b/src/main/resources/org/apache/commons/validator/resources/validator_1_3_0.dtd
index f644aeb..4fdac86 100644
--- a/src/main/resources/org/apache/commons/validator/resources/validator_1_3_0.dtd
+++ b/src/main/resources/org/apache/commons/validator/resources/validator_1_3_0.dtd
@@ -25,7 +25,6 @@
      "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.3.0//EN"
      "http://jakarta.apache.org/commons/dtds/validator_1_3_0.dtd">
 
-    $Id$
 -->
 
 
diff --git a/src/main/resources/org/apache/commons/validator/resources/validator_1_4_0.dtd b/src/main/resources/org/apache/commons/validator/resources/validator_1_4_0.dtd
index b446ab7..94855e2 100644
--- a/src/main/resources/org/apache/commons/validator/resources/validator_1_4_0.dtd
+++ b/src/main/resources/org/apache/commons/validator/resources/validator_1_4_0.dtd
@@ -25,7 +25,6 @@
      "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 1.4.0//EN"
      "http://commons.apache.org/dtds/validator_1_4_0.dtd">
 
-    $Id$
 -->
 
 
diff --git a/src/site/xdoc/download_validator.xml b/src/site/xdoc/download_validator.xml
index 688df90..0fa020c 100644
--- a/src/site/xdoc/download_validator.xml
+++ b/src/site/xdoc/download_validator.xml
@@ -107,38 +107,38 @@
         failing that using the <code>SHA512</code> hash (<code>*.sha512</code> checksum files).
       </p>
       <p>
-        The <a href="https://www.apache.org/dist/commons/KEYS">KEYS</a>
+        The <a href="https://downloads.apache.org/commons/KEYS">KEYS</a>
         file contains the public PGP keys used by Apache Commons developers
         to sign releases.
       </p>
     </subsection>
     </section>
-    <section name="Apache Commons Validator 1.7 (requires JDK 1.7)">
+    <section name="Apache Commons Validator 1.8.0 (requires JDK 1.8)">
       <subsection name="Binaries">
         <table>
           <tr>
-              <td><a href="[preferred]/commons/validator/binaries/commons-validator-1.7-bin.tar.gz">commons-validator-1.7-bin.tar.gz</a></td>
-              <td><a href="https://www.apache.org/dist/commons/validator/binaries/commons-validator-1.7-bin.tar.gz.sha512">sha512</a></td>
-              <td><a href="https://www.apache.org/dist/commons/validator/binaries/commons-validator-1.7-bin.tar.gz.asc">pgp</a></td>
+              <td><a href="[preferred]/commons/validator/binaries/commons-validator-1.8.0-bin.tar.gz">commons-validator-1.8.0-bin.tar.gz</a></td>
+              <td><a href="https://downloads.apache.org/commons/validator/binaries/commons-validator-1.8.0-bin.tar.gz.sha512">sha512</a></td>
+              <td><a href="https://downloads.apache.org/commons/validator/binaries/commons-validator-1.8.0-bin.tar.gz.asc">pgp</a></td>
           </tr>
           <tr>
-              <td><a href="[preferred]/commons/validator/binaries/commons-validator-1.7-bin.zip">commons-validator-1.7-bin.zip</a></td>
-              <td><a href="https://www.apache.org/dist/commons/validator/binaries/commons-validator-1.7-bin.zip.sha512">sha512</a></td>
-              <td><a href="https://www.apache.org/dist/commons/validator/binaries/commons-validator-1.7-bin.zip.asc">pgp</a></td>
+              <td><a href="[preferred]/commons/validator/binaries/commons-validator-1.8.0-bin.zip">commons-validator-1.8.0-bin.zip</a></td>
+              <td><a href="https://downloads.apache.org/commons/validator/binaries/commons-validator-1.8.0-bin.zip.sha512">sha512</a></td>
+              <td><a href="https://downloads.apache.org/commons/validator/binaries/commons-validator-1.8.0-bin.zip.asc">pgp</a></td>
           </tr>
         </table>
       </subsection>
       <subsection name="Source">
         <table>
           <tr>
-              <td><a href="[preferred]/commons/validator/source/commons-validator-1.7-src.tar.gz">commons-validator-1.7-src.tar.gz</a></td>
-              <td><a href="https://www.apache.org/dist/commons/validator/source/commons-validator-1.7-src.tar.gz.sha512">sha512</a></td>
-              <td><a href="https://www.apache.org/dist/commons/validator/source/commons-validator-1.7-src.tar.gz.asc">pgp</a></td>
+              <td><a href="[preferred]/commons/validator/source/commons-validator-1.8.0-src.tar.gz">commons-validator-1.8.0-src.tar.gz</a></td>
+              <td><a href="https://downloads.apache.org/commons/validator/source/commons-validator-1.8.0-src.tar.gz.sha512">sha512</a></td>
+              <td><a href="https://downloads.apache.org/commons/validator/source/commons-validator-1.8.0-src.tar.gz.asc">pgp</a></td>
           </tr>
           <tr>
-              <td><a href="[preferred]/commons/validator/source/commons-validator-1.7-src.zip">commons-validator-1.7-src.zip</a></td>
-              <td><a href="https://www.apache.org/dist/commons/validator/source/commons-validator-1.7-src.zip.sha512">sha512</a></td>
-              <td><a href="https://www.apache.org/dist/commons/validator/source/commons-validator-1.7-src.zip.asc">pgp</a></td>
+              <td><a href="[preferred]/commons/validator/source/commons-validator-1.8.0-src.zip">commons-validator-1.8.0-src.zip</a></td>
+              <td><a href="https://downloads.apache.org/commons/validator/source/commons-validator-1.8.0-src.zip.sha512">sha512</a></td>
+              <td><a href="https://downloads.apache.org/commons/validator/source/commons-validator-1.8.0-src.zip.asc">pgp</a></td>
           </tr>
         </table>
       </subsection>
diff --git a/src/site/xdoc/issue-tracking.xml b/src/site/xdoc/issue-tracking.xml
index 454f027..a8636b5 100644
--- a/src/site/xdoc/issue-tracking.xml
+++ b/src/site/xdoc/issue-tracking.xml
@@ -85,7 +85,7 @@
       </p>
 
       <p>
-      For more information on subversion and creating patches see the
+      For more information on creating patches see the
       <a href="https://www.apache.org/dev/contributors.html">Apache Contributors Guide</a>.
       </p>
 
diff --git a/src/site/xdoc/mail-lists.xml b/src/site/xdoc/mail-lists.xml
index 0654e3c..1466d3b 100644
--- a/src/site/xdoc/mail-lists.xml
+++ b/src/site/xdoc/mail-lists.xml
@@ -59,9 +59,9 @@
       </p>
       <p>
         Questions related to the usage of Apache Commons Validator should be posted to the
-        <a href="https://mail-archives.apache.org/mod_mbox/commons-user/">User List</a>.
+        <a href="https://lists.apache.org/list.html?user@commons.apache.org">User List</a>.
         <br />
-        The <a href="https://mail-archives.apache.org/mod_mbox/commons-dev/">Developer List</a>
+        The <a href="https://lists.apache.org/list.html?dev@commons.apache.org">Developer List</a>
         is for questions and discussion related to the development of Apache Commons Validator.
         <br />
         Please do not cross-post; developers are also subscribed to the user list.
@@ -70,8 +70,10 @@
         to subscribe.
       </p>
       <p>
-        <strong>Note:</strong> please don't send patches or attachments to any of the mailing lists.
+        <strong>Note:</strong> please don't send patches or attachments to any of the mailing lists;
+        most of the lists are set up to drop attachments.
         Patches are best handled via the <a href="issue-tracking.html">Issue Tracking</a> system.
+        If you have a GitHub account, most components also accept PRs (pull requests).
         Otherwise, please upload the file to a public server and include the URL in the mail.
       </p>
     </section>
@@ -105,10 +107,11 @@
           <td><a href="mailto:user-subscribe@commons.apache.org">Subscribe</a></td>
           <td><a href="mailto:user-unsubscribe@commons.apache.org">Unsubscribe</a></td>
           <td><a href="mailto:user@commons.apache.org?subject=[validator]">Post</a></td>
-          <td><a href="https://mail-archives.apache.org/mod_mbox/commons-user/">mail-archives.apache.org</a></td>
-          <td><a href="https://markmail.org/list/org.apache.commons.users/">markmail.org</a><br />
-              <a href="https://www.mail-archive.com/user@commons.apache.org/">www.mail-archive.com</a><br />
-              <a href="https://news.gmane.org/gmane.comp.jakarta.commons.devel">news.gmane.org</a>
+          <td>
+              <a href="https://lists.apache.org/list.html?user@commons.apache.org">lists.apache.org</a>
+          </td>
+          <td>
+              <a href="https://www.mail-archive.com/user@commons.apache.org/">www.mail-archive.com</a>
           </td>
         </tr>
 
@@ -123,10 +126,11 @@
           <td><a href="mailto:dev-subscribe@commons.apache.org">Subscribe</a></td>
           <td><a href="mailto:dev-unsubscribe@commons.apache.org">Unsubscribe</a></td>
           <td><a href="mailto:dev@commons.apache.org?subject=[validator]">Post</a></td>
-          <td><a href="https://mail-archives.apache.org/mod_mbox/commons-dev/">mail-archives.apache.org</a></td>
-          <td><a href="https://markmail.org/list/org.apache.commons.dev/">markmail.org</a><br />
-              <a href="https://www.mail-archive.com/dev@commons.apache.org/">www.mail-archive.com</a><br />
-              <a href="https://news.gmane.org/gmane.comp.jakarta.commons.devel">news.gmane.org</a>
+          <td>
+              <a href="https://lists.apache.org/list.html?dev@commons.apache.org">lists.apache.org</a>
+          </td>
+          <td>
+              <a href="https://www.mail-archive.com/dev@commons.apache.org/">www.mail-archive.com</a>
           </td>
         </tr>
 
@@ -141,8 +145,10 @@
           <td><a href="mailto:issues-subscribe@commons.apache.org">Subscribe</a></td>
           <td><a href="mailto:issues-unsubscribe@commons.apache.org">Unsubscribe</a></td>
           <td><i>read only</i></td>
-          <td><a href="https://mail-archives.apache.org/mod_mbox/commons-issues/">mail-archives.apache.org</a></td>
-          <td><a href="https://markmail.org/list/org.apache.commons.issues/">markmail.org</a><br />
+          <td>
+              <a href="https://lists.apache.org/list.html?issues@commons.apache.org">lists.apache.org</a>
+          </td>
+          <td>
               <a href="https://www.mail-archive.com/issues@commons.apache.org/">www.mail-archive.com</a>
           </td>
         </tr>
@@ -152,14 +158,16 @@
           <td>
             <strong>Commons Commits List</strong>
             <br /><br />
-            Only for e-mails automatically generated by the <a href="scm.html">source control</a> sytem.
+            Only for e-mails automatically generated by the <a href="scm.html">source control</a> system.
             <br /><br />
           </td>
           <td><a href="mailto:commits-subscribe@commons.apache.org">Subscribe</a></td>
           <td><a href="mailto:commits-unsubscribe@commons.apache.org">Unsubscribe</a></td>
           <td><i>read only</i></td>
-          <td><a href="https://mail-archives.apache.org/mod_mbox/commons-commits/">mail-archives.apache.org</a></td>
-          <td><a href="https://markmail.org/list/org.apache.commons.commits/">markmail.org</a><br />
+          <td>
+              <a href="https://lists.apache.org/list.html?commits@commons.apache.org">lists.apache.org</a>
+          </td>
+          <td>
               <a href="https://www.mail-archive.com/commits@commons.apache.org/">www.mail-archive.com</a>
           </td>
         </tr>
@@ -191,11 +199,11 @@
           <td><a class="externalLink" href="mailto:announce-subscribe@apache.org">Subscribe</a></td>
           <td><a class="externalLink" href="mailto:announce-unsubscribe@apache.org">Unsubscribe</a></td>
           <td><i>read only</i></td>
-          <td><a class="externalLink" href="https://mail-archives.apache.org/mod_mbox/www-announce/">mail-archives.apache.org</a></td>
-          <td><a class="externalLink" href="https://markmail.org/list/org.apache.announce/">markmail.org</a><br />
-              <a class="externalLink" href="https://old.nabble.com/Apache-News-and-Announce-f109.html">old.nabble.com</a><br />
-              <a class="externalLink" href="https://www.mail-archive.com/announce@apache.org/">www.mail-archive.com</a><br />
-              <a class="externalLink" href="https://news.gmane.org/gmane.comp.apache.announce">news.gmane.org</a>
+          <td>
+              <a class="externalLink" href="https://lists.apache.org/list.html?announce@apache.org">lists.apache.org</a>
+          </td>
+          <td>
+              <a class="externalLink" href="https://www.mail-archive.com/announce@apache.org/">www.mail-archive.com</a>
           </td>
         </tr>
       </table>
diff --git a/src/site/xdoc/validator_2_0_0_proposal.dtd b/src/site/xdoc/validator_2_0_0_proposal.dtd
index c5428fe..866e812 100644
--- a/src/site/xdoc/validator_2_0_0_proposal.dtd
+++ b/src/site/xdoc/validator_2_0_0_proposal.dtd
@@ -25,7 +25,6 @@
      "-//Apache Software Foundation//DTD Commons Validator Rules Configuration 2.0.0//EN"
      "http://jakarta.apache.org/commons/dtds/validator_2_0_0.dtd">
 
-    $Id$
 -->
 
 <!--
diff --git a/src/test/java/org/apache/commons/validator/AbstractCommonTest.java b/src/test/java/org/apache/commons/validator/AbstractCommonTest.java
index 126c8fa..9507770 100644
--- a/src/test/java/org/apache/commons/validator/AbstractCommonTest.java
+++ b/src/test/java/org/apache/commons/validator/AbstractCommonTest.java
@@ -21,25 +21,19 @@
 
 import org.xml.sax.SAXException;
 
-import junit.framework.TestCase;
-
 /**
  * Consolidates reading in XML config file into parent class.
  */
-abstract public class AbstractCommonTest extends TestCase {
+abstract public class AbstractCommonTest {
 
     /**
      * Resources used for validation tests.
      */
     protected ValidatorResources resources;
-
-    public AbstractCommonTest(final String string) {
-        super(string);
-    }
+    protected String name;
 
     /**
-     * Load <code>ValidatorResources</code> from
-     * validator-numeric.xml.
+     * Load <code>ValidatorResources</code> from validator-numeric.xml.
      */
     protected void loadResources(final String file) throws IOException, SAXException {
         // Load resources
diff --git a/src/test/java/org/apache/commons/validator/AbstractNumberTest.java b/src/test/java/org/apache/commons/validator/AbstractNumberTest.java
index 3fb67bf..2063d11 100644
--- a/src/test/java/org/apache/commons/validator/AbstractNumberTest.java
+++ b/src/test/java/org/apache/commons/validator/AbstractNumberTest.java
@@ -16,18 +16,23 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.IOException;
 
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
 /**
  * Abstracts number unit tests methods.
  */
-abstract public class AbstractNumberTest extends AbstractCommonTest {
+public abstract class AbstractNumberTest extends AbstractCommonTest {
 
     /**
-     * The key used to retrieve the set of validation
-     * rules from the xml file.
+     * The key used to retrieve the set of validation rules from the xml file.
      */
     protected String FORM_KEY;
 
@@ -36,28 +41,23 @@
      */
     protected String ACTION;
 
-
-    public AbstractNumberTest(final String name) {
-        super(name);
-    }
-
     /**
-     * Load <code>ValidatorResources</code> from
-     * validator-numeric.xml.
+     * Load <code>ValidatorResources</code> from validator-numeric.xml.
      */
-    @Override
+    @BeforeEach
     protected void setUp() throws IOException, SAXException {
         // Load resources
         loadResources("TestNumber-config.xml");
     }
 
-    @Override
+    @AfterEach
     protected void tearDown() {
     }
 
     /**
      * Tests the number validation.
      */
+    @Test
     public void testNumber() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -68,6 +68,7 @@
     /**
      * Tests the float validation failure.
      */
+    @Test
     public void testNumberFailure() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -75,10 +76,10 @@
     }
 
     /**
-     * Utlity class to run a test on a value.
+     * Utility class to run a test on a value.
      *
-     * @param    info    Value to run test on.
-     * @param    passed    Whether or not the test is expected to pass.
+     * @param info   Value to run test on.
+     * @param passed Whether or not the test is expected to pass.
      */
     protected void valueTest(final Object info, final boolean passed) throws ValidatorException {
         // Construct validator based on the loaded resources
@@ -95,14 +96,14 @@
         // throw this
         final ValidatorResults results = validator.validate();
 
-        assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
         final ValidatorResult result = results.getValidatorResult("value");
 
-        assertNotNull(ACTION + " value ValidatorResult should not be null.", result);
-        assertTrue(ACTION + " value ValidatorResult should contain the '" + ACTION + "' action.", result.containsAction(ACTION));
-        assertTrue(ACTION + " value ValidatorResult for the '" + ACTION + "' action should have " + (passed ? "passed" : "failed") + ".", (passed ? result.isValid(ACTION) : !result.isValid(ACTION)));
+        assertNotNull(result, () -> ACTION + " value ValidatorResult should not be null.");
+        assertTrue(result.containsAction(ACTION), () -> ACTION + " value ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(passed ? result.isValid(ACTION) : !result.isValid(ACTION),
+                () -> ACTION + " value ValidatorResult for the '" + ACTION + "' action should have " + (passed ? "passed" : "failed") + ".");
     }
 
-
 }
diff --git a/src/test/java/org/apache/commons/validator/ByteTest.java b/src/test/java/org/apache/commons/validator/ByteTest.java
index d7f5984..142a11a 100644
--- a/src/test/java/org/apache/commons/validator/ByteTest.java
+++ b/src/test/java/org/apache/commons/validator/ByteTest.java
@@ -16,15 +16,14 @@
  */
 package org.apache.commons.validator;
 
-
+import org.junit.jupiter.api.Test;
 
 /**
  * Performs Validation Test for <code>byte</code> validations.
  */
 public class ByteTest extends AbstractNumberTest {
 
-    public ByteTest(final String name) {
-        super(name);
+    public ByteTest() {
         ACTION = "byte";
         FORM_KEY = "byteForm";
     }
@@ -32,6 +31,7 @@
     /**
      * Tests the byte validation.
      */
+    @Test
     public void testByte() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -41,33 +41,13 @@
     }
 
     /**
-     * Tests the byte validation.
-     */
-    public void testByteMin() throws ValidatorException {
-        // Create bean to run test on.
-        final ValueBean info = new ValueBean();
-        info.setValue(Byte.toString(Byte.MIN_VALUE));
-
-        valueTest(info, true);
-    }
-
-    /**
-     * Tests the byte validation.
-     */
-    public void testByteMax() throws ValidatorException {
-        // Create bean to run test on.
-        final ValueBean info = new ValueBean();
-        info.setValue(Byte.toString(Byte.MAX_VALUE));
-
-        valueTest(info, true);
-    }
-
-    /**
      * Tests the byte validation failure.
      */
-    public void testByteFailure() throws ValidatorException {
+    @Test
+    public void testByteBeyondMax() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
+        info.setValue(Byte.MAX_VALUE + "1");
 
         valueTest(info, false);
     }
@@ -75,6 +55,7 @@
     /**
      * Tests the byte validation failure.
      */
+    @Test
     public void testByteBeyondMin() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -86,12 +67,36 @@
     /**
      * Tests the byte validation failure.
      */
-    public void testByteBeyondMax() throws ValidatorException {
+    @Test
+    public void testByteFailure() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
-        info.setValue(Byte.MAX_VALUE + "1");
 
         valueTest(info, false);
     }
 
+    /**
+     * Tests the byte validation.
+     */
+    @Test
+    public void testByteMax() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+        info.setValue(Byte.toString(Byte.MAX_VALUE));
+
+        valueTest(info, true);
+    }
+
+    /**
+     * Tests the byte validation.
+     */
+    @Test
+    public void testByteMin() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+        info.setValue(Byte.toString(Byte.MIN_VALUE));
+
+        valueTest(info, true);
+    }
+
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/CreditCardValidatorTest.java b/src/test/java/org/apache/commons/validator/CreditCardValidatorTest.java
index c1afe8e..ebd7a0b 100644
--- a/src/test/java/org/apache/commons/validator/CreditCardValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/CreditCardValidatorTest.java
@@ -16,7 +16,10 @@
  */
 package org.apache.commons.validator;
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
 
 /**
  * Test the CreditCardValidator class.
@@ -24,42 +27,30 @@
  * @deprecated this test can be removed when the deprecated class is removed
  */
 @Deprecated
-public class CreditCardValidatorTest extends TestCase {
+public class CreditCardValidatorTest {
+
+    /**
+     * Test a custom implementation of CreditCardType.
+     */
+    private static class DinersClub implements CreditCardValidator.CreditCardType {
+        private static final String PREFIX = "300,301,302,303,304,305,";
+
+        @Override
+        public boolean matches(final String card) {
+            final String prefix = card.substring(0, 3) + ",";
+            return PREFIX.contains(prefix) && card.length() == 14;
+        }
+    }
 
     private static final String VALID_VISA = "4417123456789113";
     private static final String VALID_SHORT_VISA = "4222222222222";
     private static final String VALID_AMEX = "378282246310005";
     private static final String VALID_MASTERCARD = "5105105105105100";
     private static final String VALID_DISCOVER = "6011000990139424";
+
     private static final String VALID_DINERS = "30569309025904";
 
-    /**
-     * Constructor for CreditCardValidatorTest.
-     */
-    public CreditCardValidatorTest(final String name) {
-        super(name);
-    }
-
-    public void testIsValid() {
-        CreditCardValidator ccv = new CreditCardValidator();
-
-        assertFalse(ccv.isValid(null));
-        assertFalse(ccv.isValid(""));
-        assertFalse(ccv.isValid("123456789012"));   // too short
-        assertFalse(ccv.isValid("12345678901234567890"));   // too long
-        assertFalse(ccv.isValid("4417123456789112"));
-        assertFalse(ccv.isValid("4417q23456w89113"));
-        assertTrue(ccv.isValid(VALID_VISA));
-        assertTrue(ccv.isValid(VALID_SHORT_VISA));
-        assertTrue(ccv.isValid(VALID_AMEX));
-        assertTrue(ccv.isValid(VALID_MASTERCARD));
-        assertTrue(ccv.isValid(VALID_DISCOVER));
-
-        // disallow Visa so it should fail even with good number
-        ccv = new CreditCardValidator(CreditCardValidator.AMEX);
-        assertFalse(ccv.isValid("4417123456789113"));
-    }
-
+    @Test
     public void testAddAllowedCardType() {
         final CreditCardValidator ccv = new CreditCardValidator(CreditCardValidator.NONE);
         // Turned off all cards so even valid numbers should fail
@@ -73,16 +64,25 @@
         assertTrue(ccv.isValid(VALID_DINERS));
     }
 
-    /**
-     * Test a custom implementation of CreditCardType.
-     */
-    private static class DinersClub implements CreditCardValidator.CreditCardType {
-        private static final String PREFIX = "300,301,302,303,304,305,";
-        @Override
-        public boolean matches(final String card) {
-            final String prefix = card.substring(0, 3) + ",";
-            return ((PREFIX.contains(prefix)) && (card.length() == 14));
-        }
+    @Test
+    public void testIsValid() {
+        CreditCardValidator ccv = new CreditCardValidator();
+
+        assertFalse(ccv.isValid(null));
+        assertFalse(ccv.isValid(""));
+        assertFalse(ccv.isValid("123456789012")); // too short
+        assertFalse(ccv.isValid("12345678901234567890")); // too long
+        assertFalse(ccv.isValid("4417123456789112"));
+        assertFalse(ccv.isValid("4417q23456w89113"));
+        assertTrue(ccv.isValid(VALID_VISA));
+        assertTrue(ccv.isValid(VALID_SHORT_VISA));
+        assertTrue(ccv.isValid(VALID_AMEX));
+        assertTrue(ccv.isValid(VALID_MASTERCARD));
+        assertTrue(ccv.isValid(VALID_DISCOVER));
+
+        // disallow Visa so it should fail even with good number
+        ccv = new CreditCardValidator(CreditCardValidator.AMEX);
+        assertFalse(ccv.isValid("4417123456789113"));
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/CustomValidatorResourcesTest.java b/src/test/java/org/apache/commons/validator/CustomValidatorResourcesTest.java
index fc42cca..4c99c26 100644
--- a/src/test/java/org/apache/commons/validator/CustomValidatorResourcesTest.java
+++ b/src/test/java/org/apache/commons/validator/CustomValidatorResourcesTest.java
@@ -16,53 +16,50 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.io.InputStream;
 
-import junit.framework.TestCase;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * Test custom ValidatorResources.
  */
-public class CustomValidatorResourcesTest extends TestCase {
+public class CustomValidatorResourcesTest {
 
     /**
-     * Construct a test case with the specified name.
-     * @param name Name of the test
+     * Sets up.
      */
-    public CustomValidatorResourcesTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set up.
-     */
-    @Override
+    @BeforeEach
     protected void setUp() {
     }
 
     /**
      * Tear Down
      */
-    @Override
+    @AfterEach
     protected void tearDown() {
     }
 
     /**
      * Test creating a custom validator resources.
      */
+    @Test
     public void testCustomResources() {
         // Load resources
         InputStream in = null;
         try {
             in = this.getClass().getResourceAsStream("TestNumber-config.xml");
-        } catch(final Exception e) {
+        } catch (final Exception e) {
             fail("Error loading resources: " + e);
         } finally {
             try {
                 if (in != null) {
                     in.close();
                 }
-            } catch(final Exception e) {
+            } catch (final Exception e) {
             }
         }
     }
diff --git a/src/test/java/org/apache/commons/validator/DateTest.java b/src/test/java/org/apache/commons/validator/DateTest.java
index feddd33..a24a33f 100644
--- a/src/test/java/org/apache/commons/validator/DateTest.java
+++ b/src/test/java/org/apache/commons/validator/DateTest.java
@@ -16,9 +16,14 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.IOException;
 import java.util.Locale;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
 /**
@@ -27,8 +32,7 @@
 public class DateTest extends AbstractCommonTest {
 
     /**
-     * The key used to retrieve the set of validation
-     * rules from the xml file.
+     * The key used to retrieve the set of validation rules from the xml file.
      */
     protected String FORM_KEY = "dateForm";
 
@@ -37,16 +41,10 @@
      */
     protected String ACTION = "date";
 
-
-    public DateTest(final String name) {
-        super(name);
-    }
-
     /**
-     * Load <code>ValidatorResources</code> from
-     * validator-numeric.xml.
+     * Load <code>ValidatorResources</code> from validator-numeric.xml.
      */
-    @Override
+    @BeforeEach
     protected void setUp() throws IOException, SAXException {
         // Load resources
         loadResources("DateTest-config.xml");
@@ -55,6 +53,18 @@
     /**
      * Tests the date validation.
      */
+    @Test
+    public void testInvalidDate() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+        info.setValue("12/01as/2005");
+        valueTest(info, false);
+    }
+
+    /**
+     * Tests the date validation.
+     */
+    @Test
     public void testValidDate() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -63,21 +73,10 @@
     }
 
     /**
-     * Tests the date validation.
-     */
-    public void testInvalidDate() throws ValidatorException {
-        // Create bean to run test on.
-        final ValueBean info = new ValueBean();
-        info.setValue("12/01as/2005");
-        valueTest(info, false);
-    }
-
-
-    /**
      * Utlity class to run a test on a value.
      *
-     * @param    info    Value to run test on.
-     * @param    passed    Whether or not the test is expected to pass.
+     * @param info   Value to run test on.
+     * @param passed Whether or not the test is expected to pass.
      */
     protected void valueTest(final Object info, final boolean passed) throws ValidatorException {
         // Construct validator based on the loaded resources
@@ -95,14 +94,14 @@
         // throw this
         final ValidatorResults results = validator.validate();
 
-        assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
         final ValidatorResult result = results.getValidatorResult("value");
 
-        assertNotNull(ACTION + " value ValidatorResult should not be null.", result);
-        assertTrue(ACTION + " value ValidatorResult should contain the '" + ACTION + "' action.", result.containsAction(ACTION));
-        assertTrue(ACTION + " value ValidatorResult for the '" + ACTION + "' action should have " + (passed ? "passed" : "failed") + ".", (passed ? result.isValid(ACTION) : !result.isValid(ACTION)));
+        assertNotNull(result, () -> ACTION + " value ValidatorResult should not be null.");
+        assertTrue(result.containsAction(ACTION), () -> ACTION + " value ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(passed ? result.isValid(ACTION) : !result.isValid(ACTION),
+                () -> ACTION + " value ValidatorResult for the '" + ACTION + "' action should have " + (passed ? "passed" : "failed") + ".");
     }
 
-
 }
diff --git a/src/test/java/org/apache/commons/validator/DoubleTest.java b/src/test/java/org/apache/commons/validator/DoubleTest.java
index 19d7e6c..15f2919 100644
--- a/src/test/java/org/apache/commons/validator/DoubleTest.java
+++ b/src/test/java/org/apache/commons/validator/DoubleTest.java
@@ -16,22 +16,22 @@
  */
 package org.apache.commons.validator;
 
+import org.junit.jupiter.api.Test;
 
 /**
  * Performs Validation Test for <code>double</code> validations.
  */
 public class DoubleTest extends AbstractNumberTest {
 
-    public DoubleTest(final String name) {
-        super(name);
+    public DoubleTest() {
         ACTION = "double";
         FORM_KEY = "doubleForm";
     }
 
-
     /**
      * Tests the double validation.
      */
+    @Test
     public void testDouble() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -41,19 +41,20 @@
     }
 
     /**
-     * Tests the double validation.
+     * Tests the double validation failure.
      */
-    public void testDoubleMin() throws ValidatorException {
+    @Test
+    public void testDoubleFailure() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
-        info.setValue(Double.toString(Double.MIN_VALUE));
 
-        valueTest(info, true);
+        valueTest(info, false);
     }
 
     /**
      * Tests the double validation.
      */
+    @Test
     public void testDoubleMax() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -63,13 +64,15 @@
     }
 
     /**
-     * Tests the double validation failure.
+     * Tests the double validation.
      */
-    public void testDoubleFailure() throws ValidatorException {
+    @Test
+    public void testDoubleMin() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
+        info.setValue(Double.toString(Double.MIN_VALUE));
 
-        valueTest(info, false);
+        valueTest(info, true);
     }
 
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/EmailTest.java b/src/test/java/org/apache/commons/validator/EmailTest.java
index ef00c1f..63f1ef9 100644
--- a/src/test/java/org/apache/commons/validator/EmailTest.java
+++ b/src/test/java/org/apache/commons/validator/EmailTest.java
@@ -16,8 +16,14 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.IOException;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
 /**
@@ -30,224 +36,73 @@
 public class EmailTest extends AbstractCommonTest {
 
     /**
-     * The key used to retrieve the set of validation
-     * rules from the xml file.
+     * The key used to retrieve the set of validation rules from the xml file.
      */
     protected static String FORM_KEY = "emailForm";
 
-   /**
-    * The key used to retrieve the validator action.
-    */
-   protected static String ACTION = "email";
-
-
-   public EmailTest(final String name) {
-       super(name);
-   }
-
-   /**
-    * Load <code>ValidatorResources</code> from
-    * validator-regexp.xml.
-    */
-   @Override
-protected void setUp() throws IOException, SAXException {
-      loadResources("EmailTest-config.xml");
-   }
-
-   /**
-    * Tests the e-mail validation.
-    */
-   public void testEmail() throws ValidatorException {
-      // Create bean to run test on.
-      final ValueBean info = new ValueBean();
-
-      info.setValue("jsmith@apache.org");
-      valueTest(info, true);
-   }
-
-   /**
-    * Tests the email validation with numeric domains.
-    */
-    public void testEmailWithNumericAddress() throws ValidatorException {
-        final ValueBean info = new ValueBean();
-        info.setValue("someone@[216.109.118.76]");
-        valueTest(info, true);
-        info.setValue("someone@yahoo.com");
-        valueTest(info, true);
-    }
-
     /**
-     * Tests the e-mail validation.
+     * The key used to retrieve the validator action.
      */
-    public void testEmailExtension() throws ValidatorException {
-        // Create bean to run test on.
-        final ValueBean info = new ValueBean();
-
-        info.setValue("jsmith@apache.org");
-        valueTest(info, true);
-
-        info.setValue("jsmith@apache.com");
-        valueTest(info, true);
-
-        info.setValue("jsmith@apache.net");
-        valueTest(info, true);
-
-        info.setValue("jsmith@apache.info");
-        valueTest(info, true);
-
-        info.setValue("jsmith@apache.");
-        valueTest(info, false);
-
-        info.setValue("jsmith@apache.c");
-        valueTest(info, false);
-
-        info.setValue("someone@yahoo.museum");
-        valueTest(info, true);
-
-        info.setValue("someone@yahoo.mu-seum");
-        valueTest(info, false);
-    }
-
-   /**
-    * <p>Tests the e-mail validation with a dash in
-    * the address.</p>
-    */
-   public void testEmailWithDash() throws ValidatorException {
-      // Create bean to run test on.
-      final ValueBean info = new ValueBean();
-
-      info.setValue("andy.noble@data-workshop.com");
-      valueTest(info, true);
-
-      info.setValue("andy-noble@data-workshop.-com");
-       valueTest(info, false);
-       info.setValue("andy-noble@data-workshop.c-om");
-       valueTest(info,false);
-       info.setValue("andy-noble@data-workshop.co-m");
-       valueTest(info, false);
-
-
-   }
-
-   /**
-    * Tests the e-mail validation with a dot at the end of
-    * the address.
-    */
-   public void testEmailWithDotEnd() throws ValidatorException {
-      // Create bean to run test on.
-      final ValueBean info = new ValueBean();
-
-      info.setValue("andy.noble@data-workshop.com.");
-      valueTest(info, false);
-
-   }
+    protected static String ACTION = "email";
 
     /**
-     * Tests the e-mail validation with an RCS-noncompliant character in
-     * the address.
+     * These test values derive directly from RFC 822 & Mail::RFC822::Address & RFC::RFC822::Address perl test.pl For traceability don't combine these test
+     * values with other tests.
      */
-    public void testEmailWithBogusCharacter() throws ValidatorException {
-        // Create bean to run test on.
-        final ValueBean info = new ValueBean();
-
-        info.setValue("andy.noble@\u008fdata-workshop.com");
-        valueTest(info, false);
-
-        // The ' character is valid in an email username.
-        info.setValue("andy.o'reilly@data-workshop.com");
-        valueTest(info, true);
-
-        // But not in the domain name.
-        info.setValue("andy@o'reilly.data-workshop.com");
-        valueTest(info, false);
-
-        info.setValue("foo+bar@i.am.not.in.us.example.com");
-        valueTest(info, true);
-    }
-
-   /**
-    * Tests the email validation with commas.
-    */
-    public void testEmailWithCommas() throws ValidatorException {
-        final ValueBean info = new ValueBean();
-        info.setValue("joeblow@apa,che.org");
-        valueTest(info, false);
-        info.setValue("joeblow@apache.o,rg");
-        valueTest(info, false);
-        info.setValue("joeblow@apache,org");
-        valueTest(info, false);
-
-    }
-
-   /**
-    * Tests the email validation with spaces.
-    */
-    public void testEmailWithSpaces() throws ValidatorException {
-        final ValueBean info = new ValueBean();
-        info.setValue("joeblow @apache.org");
-        valueTest(info, false);
-        info.setValue("joeblow@ apache.org");
-        valueTest(info, false);
-        info.setValue(" joeblow@apache.org");
-        valueTest(info, false);
-        info.setValue("joeblow@apache.org ");
-        valueTest(info, false);
-        info.setValue("joe blow@apache.org ");
-        valueTest(info, false);
-        info.setValue("joeblow@apa che.org ");
-        valueTest(info, false);
-        info.setValue("\"joe blow\"@apache.org");
-        valueTest(info, true);
-
-    }
-
-   /**
-    * Tests the email validation with ascii control characters.
-    * (i.e. Ascii chars 0 - 31 and 127)
-    */
-    public void testEmailWithControlChars() {
-        final EmailValidator validator = new EmailValidator();
-        for (char c = 0; c < 32; c++) {
-            assertFalse("Test control char " + ((int)c), validator.isValid("foo" + c + "bar@domain.com"));
-        }
-        assertFalse("Test control char 127", validator.isValid("foo" + ((char)127) + "bar@domain.com"));
-    }
-
-   /**
-    * Tests the e-mail validation with a user at a TLD
-    */
-   public void testEmailAtTLD() throws ValidatorException {
-      // Create bean to run test on.
-      final ValueBean info = new ValueBean();
-
-      info.setValue("m@de");
-      valueTest(info, false);
-
-       final org.apache.commons.validator.routines.EmailValidator validator =
-               org.apache.commons.validator.routines.EmailValidator.getInstance(true, true);
-      final boolean result = validator.isValid("m@de");
-      assertTrue("Result should have been true", result);
-
-   }
+    ResultPair[] testEmailFromPerl = { new ResultPair("abigail@example.com", true), new ResultPair("abigail@example.com ", true),
+            new ResultPair(" abigail@example.com", true), new ResultPair("abigail @example.com ", true), new ResultPair("*@example.net", true),
+            new ResultPair("\"\\\"\"@foo.bar", true), new ResultPair("fred&barny@example.com", true), new ResultPair("---@example.com", true),
+            new ResultPair("foo-bar@example.net", true), new ResultPair("\"127.0.0.1\"@[127.0.0.1]", true),
+            new ResultPair("Abigail <abigail@example.com>", true), new ResultPair("Abigail<abigail@example.com>", true),
+            new ResultPair("Abigail<@a,@b,@c:abigail@example.com>", true), new ResultPair("\"This is a phrase\"<abigail@example.com>", true),
+            new ResultPair("\"Abigail \"<abigail@example.com>", true), new ResultPair("\"Joe & J. Harvey\" <example @Org>", true),
+            new ResultPair("Abigail <abigail @ example.com>", true), new ResultPair("Abigail made this <  abigail   @   example  .    com    >", true),
+            new ResultPair("Abigail(the bitch)@example.com", true), new ResultPair("Abigail <abigail @ example . (bar) com >", true),
+            new ResultPair("Abigail < (one)  abigail (two) @(three)example . (bar) com (quz) >", true),
+            new ResultPair("Abigail (foo) (((baz)(nested) (comment)) ! ) < (one)  abigail (two) @(three)example . (bar) com (quz) >", true),
+            new ResultPair("Abigail <abigail(fo\\(o)@example.com>", true), new ResultPair("Abigail <abigail(fo\\)o)@example.com> ", true),
+            new ResultPair("(foo) abigail@example.com", true), new ResultPair("abigail@example.com (foo)", true),
+            new ResultPair("\"Abi\\\"gail\" <abigail@example.com>", true), new ResultPair("abigail@[example.com]", true),
+            new ResultPair("abigail@[exa\\[ple.com]", true), new ResultPair("abigail@[exa\\]ple.com]", true),
+            new ResultPair("\":sysmail\"@  Some-Group. Some-Org", true), new ResultPair("Muhammed.(I am  the greatest) Ali @(the)Vegas.WBA", true),
+            new ResultPair("mailbox.sub1.sub2@this-domain", true), new ResultPair("sub-net.mailbox@sub-domain.domain", true), new ResultPair("name:;", true),
+            new ResultPair("':;", true), new ResultPair("name:   ;", true), new ResultPair("Alfred Neuman <Neuman@BBN-TENEXA>", true),
+            new ResultPair("Neuman@BBN-TENEXA", true), new ResultPair("\"George, Ted\" <Shared@Group.Arpanet>", true),
+            new ResultPair("Wilt . (the  Stilt) Chamberlain@NBA.US", true), new ResultPair("Cruisers:  Port@Portugal, Jones@SEA;", true),
+            new ResultPair("$@[]", true), new ResultPair("*()@[]", true), new ResultPair("\"quoted ( brackets\" ( a comment )@example.com", true),
+            new ResultPair("\"Joe & J. Harvey\"\\x0D\\x0A     <ddd\\@ Org>", true), new ResultPair("\"Joe &\\x0D\\x0A J. Harvey\" <ddd \\@ Org>", true),
+            new ResultPair(
+                    "Gourmets:  Pompous Person <WhoZiWhatZit\\@Cordon-Bleu>,\\x0D\\x0A" + "        Childs\\@WGBH.Boston, \"Galloping Gourmet\"\\@\\x0D\\x0A"
+                            + "        ANT.Down-Under (Australian National Television),\\x0D\\x0A" + "        Cheapie\\@Discount-Liquors;",
+                    true),
+            new ResultPair("   Just a string", false), new ResultPair("string", false), new ResultPair("(comment)", false),
+            new ResultPair("()@example.com", false), new ResultPair("fred(&)barny@example.com", false), new ResultPair("fred\\ barny@example.com", false),
+            new ResultPair("Abigail <abi gail @ example.com>", false), new ResultPair("Abigail <abigail(fo(o)@example.com>", false),
+            new ResultPair("Abigail <abigail(fo)o)@example.com>", false), new ResultPair("\"Abi\"gail\" <abigail@example.com>", false),
+            new ResultPair("abigail@[exa]ple.com]", false), new ResultPair("abigail@[exa[ple.com]", false), new ResultPair("abigail@[exaple].com]", false),
+            new ResultPair("abigail@", false), new ResultPair("@example.com", false),
+            new ResultPair("phrase: abigail@example.com abigail@example.com ;", false), new ResultPair("invalidīŋŊchar@example.com", false) };
 
     /**
-     * Test that @localhost and @localhost.localdomain
-     *  addresses aren't declared valid by default
-     */
-    public void testEmailLocalhost() throws ValidatorException {
-       final ValueBean info = new ValueBean();
-       info.setValue("joe@localhost");
-       valueTest(info, false);
-       info.setValue("joe@localhost.localdomain");
-       valueTest(info, false);
-    }
-
-    /**
-     * Write this test according to parts of RFC, as opposed to the type of character
-     * that is being tested.
+     * Write this test based on perl Mail::RFC822::Address which takes its example email address directly from RFC822
      *
-     * <p><b>FIXME</b>: This test fails so disable it with a leading _ for 1.1.4 release.
-     * The real solution is to fix the email parsing.
+     * @throws ValidatorException
+     *
+     *                            FIXME This test fails so disable it with a leading _ for 1.1.4 release. The real solution is to fix the email parsing.
+     */
+    public void _testEmailFromPerl() throws ValidatorException {
+        final ValueBean info = new ValueBean();
+        for (final ResultPair element : testEmailFromPerl) {
+            info.setValue(element.item);
+            valueTest(info, element.valid);
+        }
+    }
+
+    /**
+     * Write this test according to parts of RFC, as opposed to the type of character that is being tested.
+     *
+     * <p>
+     * <b>FIXME</b>: This test fails so disable it with a leading _ for 1.1.4 release. The real solution is to fix the email parsing.
      *
      * @throws ValidatorException
      */
@@ -262,7 +117,7 @@
         info.setValue("joe_@apache.org");
         valueTest(info, true);
 
-        //UnQuoted Special characters are invalid
+        // UnQuoted Special characters are invalid
 
         info.setValue("joe.@apache.org");
         valueTest(info, false);
@@ -291,7 +146,7 @@
         info.setValue("joe=@apache.org");
         valueTest(info, false);
 
-        //Quoted Special characters are valid
+        // Quoted Special characters are valid
         info.setValue("\"joe.\"@apache.org");
         valueTest(info, true);
         info.setValue("\"joe+\"@apache.org");
@@ -322,125 +177,235 @@
     }
 
     /**
-     * These test values derive directly from RFC 822 &
-     * Mail::RFC822::Address & RFC::RFC822::Address perl test.pl
-     * For traceability don't combine these test values with other tests.
+     * Load <code>ValidatorResources</code> from validator-regexp.xml.
      */
-    ResultPair[] testEmailFromPerl = {
-        new ResultPair("abigail@example.com", true),
-        new ResultPair("abigail@example.com ", true),
-        new ResultPair(" abigail@example.com", true),
-        new ResultPair("abigail @example.com ", true),
-        new ResultPair("*@example.net", true),
-        new ResultPair("\"\\\"\"@foo.bar", true),
-        new ResultPair("fred&barny@example.com", true),
-        new ResultPair("---@example.com", true),
-        new ResultPair("foo-bar@example.net", true),
-        new ResultPair("\"127.0.0.1\"@[127.0.0.1]", true),
-        new ResultPair("Abigail <abigail@example.com>", true),
-        new ResultPair("Abigail<abigail@example.com>", true),
-        new ResultPair("Abigail<@a,@b,@c:abigail@example.com>", true),
-        new ResultPair("\"This is a phrase\"<abigail@example.com>", true),
-        new ResultPair("\"Abigail \"<abigail@example.com>", true),
-        new ResultPair("\"Joe & J. Harvey\" <example @Org>", true),
-        new ResultPair("Abigail <abigail @ example.com>", true),
-        new ResultPair("Abigail made this <  abigail   @   example  .    com    >", true),
-        new ResultPair("Abigail(the bitch)@example.com", true),
-        new ResultPair("Abigail <abigail @ example . (bar) com >", true),
-        new ResultPair("Abigail < (one)  abigail (two) @(three)example . (bar) com (quz) >", true),
-        new ResultPair("Abigail (foo) (((baz)(nested) (comment)) ! ) < (one)  abigail (two) @(three)example . (bar) com (quz) >", true),
-        new ResultPair("Abigail <abigail(fo\\(o)@example.com>", true),
-        new ResultPair("Abigail <abigail(fo\\)o)@example.com> ", true),
-        new ResultPair("(foo) abigail@example.com", true),
-        new ResultPair("abigail@example.com (foo)", true),
-        new ResultPair("\"Abi\\\"gail\" <abigail@example.com>", true),
-        new ResultPair("abigail@[example.com]", true),
-        new ResultPair("abigail@[exa\\[ple.com]", true),
-        new ResultPair("abigail@[exa\\]ple.com]", true),
-        new ResultPair("\":sysmail\"@  Some-Group. Some-Org", true),
-        new ResultPair("Muhammed.(I am  the greatest) Ali @(the)Vegas.WBA", true),
-        new ResultPair("mailbox.sub1.sub2@this-domain", true),
-        new ResultPair("sub-net.mailbox@sub-domain.domain", true),
-        new ResultPair("name:;", true),
-        new ResultPair("':;", true),
-        new ResultPair("name:   ;", true),
-        new ResultPair("Alfred Neuman <Neuman@BBN-TENEXA>", true),
-        new ResultPair("Neuman@BBN-TENEXA", true),
-        new ResultPair("\"George, Ted\" <Shared@Group.Arpanet>", true),
-        new ResultPair("Wilt . (the  Stilt) Chamberlain@NBA.US", true),
-        new ResultPair("Cruisers:  Port@Portugal, Jones@SEA;", true),
-        new ResultPair("$@[]", true),
-        new ResultPair("*()@[]", true),
-        new ResultPair("\"quoted ( brackets\" ( a comment )@example.com", true),
-        new ResultPair("\"Joe & J. Harvey\"\\x0D\\x0A     <ddd\\@ Org>", true),
-        new ResultPair("\"Joe &\\x0D\\x0A J. Harvey\" <ddd \\@ Org>", true),
-        new ResultPair("Gourmets:  Pompous Person <WhoZiWhatZit\\@Cordon-Bleu>,\\x0D\\x0A" +
-            "        Childs\\@WGBH.Boston, \"Galloping Gourmet\"\\@\\x0D\\x0A" +
-            "        ANT.Down-Under (Australian National Television),\\x0D\\x0A" +
-            "        Cheapie\\@Discount-Liquors;", true),
-        new ResultPair("   Just a string", false),
-        new ResultPair("string", false),
-        new ResultPair("(comment)", false),
-        new ResultPair("()@example.com", false),
-        new ResultPair("fred(&)barny@example.com", false),
-        new ResultPair("fred\\ barny@example.com", false),
-        new ResultPair("Abigail <abi gail @ example.com>", false),
-        new ResultPair("Abigail <abigail(fo(o)@example.com>", false),
-        new ResultPair("Abigail <abigail(fo)o)@example.com>", false),
-        new ResultPair("\"Abi\"gail\" <abigail@example.com>", false),
-        new ResultPair("abigail@[exa]ple.com]", false),
-        new ResultPair("abigail@[exa[ple.com]", false),
-        new ResultPair("abigail@[exaple].com]", false),
-        new ResultPair("abigail@", false),
-        new ResultPair("@example.com", false),
-        new ResultPair("phrase: abigail@example.com abigail@example.com ;", false),
-        new ResultPair("invalidīŋŊchar@example.com", false)
-    };
-
-    /**
-     * Write this test based on perl Mail::RFC822::Address
-     * which takes its example email address directly from RFC822
-     *
-     * @throws ValidatorException
-     *
-     * FIXME This test fails so disable it with a leading _ for 1.1.4 release.
-     * The real solution is to fix the email parsing.
-     */
-    public void _testEmailFromPerl() throws ValidatorException {
-        final ValueBean info = new ValueBean();
-        for (final ResultPair element : testEmailFromPerl) {
-            info.setValue(element.item);
-            valueTest(info, element.valid);
-        }
+    @BeforeEach
+    protected void setUp() throws IOException, SAXException {
+        loadResources("EmailTest-config.xml");
     }
 
-   /**
-    * Utlity class to run a test on a value.
-    *
-    * @param info    Value to run test on.
-    * @param passed    Whether or not the test is expected to pass.
-    */
-   private void valueTest(final ValueBean info, final boolean passed) throws ValidatorException {
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, info);
+    /**
+     * Tests the e-mail validation.
+     */
+    @Test
+    public void testEmail() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
 
-      // Get results of the validation.
-      // throws ValidatorException,
-      // but we aren't catching for testing
-      // since no validation methods we use
-      // throw this
-      final ValidatorResults results = validator.validate();
+        info.setValue("jsmith@apache.org");
+        valueTest(info, true);
+    }
 
-      assertNotNull("Results are null.", results);
+    /**
+     * Tests the e-mail validation with a user at a TLD
+     */
+    @Test
+    public void testEmailAtTLD() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
 
-      final ValidatorResult result = results.getValidatorResult("value");
+        info.setValue("m@de");
+        valueTest(info, false);
 
-      assertNotNull(ACTION + " value ValidatorResult should not be null.", result);
-      assertTrue("Value "+info.getValue()+" ValidatorResult should contain the '" + ACTION +"' action.", result.containsAction(ACTION));
-      assertTrue("Value "+info.getValue()+"ValidatorResult for the '" + ACTION +"' action should have " + (passed ? "passed" : "failed") + ".", (passed ? result.isValid(ACTION) : !result.isValid(ACTION)));
+        final org.apache.commons.validator.routines.EmailValidator validator = org.apache.commons.validator.routines.EmailValidator.getInstance(true, true);
+        final boolean result = validator.isValid("m@de");
+        assertTrue(result, "Result should have been true");
+
+    }
+
+    /**
+     * Tests the e-mail validation.
+     */
+    @Test
+    public void testEmailExtension() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+
+        info.setValue("jsmith@apache.org");
+        valueTest(info, true);
+
+        info.setValue("jsmith@apache.com");
+        valueTest(info, true);
+
+        info.setValue("jsmith@apache.net");
+        valueTest(info, true);
+
+        info.setValue("jsmith@apache.info");
+        valueTest(info, true);
+
+        info.setValue("jsmith@apache.");
+        valueTest(info, false);
+
+        info.setValue("jsmith@apache.c");
+        valueTest(info, false);
+
+        info.setValue("someone@yahoo.museum");
+        valueTest(info, true);
+
+        info.setValue("someone@yahoo.mu-seum");
+        valueTest(info, false);
+    }
+
+    /**
+     * Test that @localhost and @localhost.localdomain addresses aren't declared valid by default
+     */
+    @Test
+    public void testEmailLocalhost() throws ValidatorException {
+        final ValueBean info = new ValueBean();
+        info.setValue("joe@localhost");
+        valueTest(info, false);
+        info.setValue("joe@localhost.localdomain");
+        valueTest(info, false);
+    }
+
+    /**
+     * Tests the e-mail validation with an RCS-noncompliant character in the address.
+     */
+    @Test
+    public void testEmailWithBogusCharacter() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+
+        info.setValue("andy.noble@\u008fdata-workshop.com");
+        valueTest(info, false);
+
+        // The ' character is valid in an email username.
+        info.setValue("andy.o'reilly@data-workshop.com");
+        valueTest(info, true);
+
+        // But not in the domain name.
+        info.setValue("andy@o'reilly.data-workshop.com");
+        valueTest(info, false);
+
+        info.setValue("foo+bar@i.am.not.in.us.example.com");
+        valueTest(info, true);
+    }
+
+    /**
+     * Tests the email validation with commas.
+     */
+    @Test
+    public void testEmailWithCommas() throws ValidatorException {
+        final ValueBean info = new ValueBean();
+        info.setValue("joeblow@apa,che.org");
+        valueTest(info, false);
+        info.setValue("joeblow@apache.o,rg");
+        valueTest(info, false);
+        info.setValue("joeblow@apache,org");
+        valueTest(info, false);
+
+    }
+
+    /**
+     * Tests the email validation with ASCII control characters. (i.e. ASCII chars 0 - 31 and 127)
+     */
+    @Test
+    public void testEmailWithControlChars() {
+        final EmailValidator validator = new EmailValidator();
+        for (char c = 0; c < 32; c++) {
+            assertFalse(validator.isValid("foo" + c + "bar@domain.com"), "Test control char " + (int) c);
+        }
+        assertFalse(validator.isValid("foo" + (char) 127 + "bar@domain.com"), "Test control char 127");
+    }
+
+    /**
+     * <p>
+     * Tests the e-mail validation with a dash in the address.
+     * </p>
+     */
+    @Test
+    public void testEmailWithDash() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+
+        info.setValue("andy.noble@data-workshop.com");
+        valueTest(info, true);
+
+        info.setValue("andy-noble@data-workshop.-com");
+        valueTest(info, false);
+        info.setValue("andy-noble@data-workshop.c-om");
+        valueTest(info, false);
+        info.setValue("andy-noble@data-workshop.co-m");
+        valueTest(info, false);
+
+    }
+
+    /**
+     * Tests the e-mail validation with a dot at the end of the address.
+     */
+    @Test
+    public void testEmailWithDotEnd() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+
+        info.setValue("andy.noble@data-workshop.com.");
+        valueTest(info, false);
+
+    }
+
+    /**
+     * Tests the email validation with numeric domains.
+     */
+    @Test
+    public void testEmailWithNumericAddress() throws ValidatorException {
+        final ValueBean info = new ValueBean();
+        info.setValue("someone@[216.109.118.76]");
+        valueTest(info, true);
+        info.setValue("someone@yahoo.com");
+        valueTest(info, true);
+    }
+
+    /**
+     * Tests the email validation with spaces.
+     */
+    @Test
+    public void testEmailWithSpaces() throws ValidatorException {
+        final ValueBean info = new ValueBean();
+        info.setValue("joeblow @apache.org");
+        valueTest(info, false);
+        info.setValue("joeblow@ apache.org");
+        valueTest(info, false);
+        info.setValue(" joeblow@apache.org");
+        valueTest(info, false);
+        info.setValue("joeblow@apache.org ");
+        valueTest(info, false);
+        info.setValue("joe blow@apache.org ");
+        valueTest(info, false);
+        info.setValue("joeblow@apa che.org ");
+        valueTest(info, false);
+        info.setValue("\"joe blow\"@apache.org");
+        valueTest(info, true);
+
+    }
+
+    /**
+     * Utlity class to run a test on a value.
+     *
+     * @param info   Value to run test on.
+     * @param passed Whether or not the test is expected to pass.
+     */
+    private void valueTest(final ValueBean info, final boolean passed) throws ValidatorException {
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, info);
+
+        // Get results of the validation.
+        // throws ValidatorException,
+        // but we aren't catching for testing
+        // since no validation methods we use
+        // throw this
+        final ValidatorResults results = validator.validate();
+
+        assertNotNull(results, "Results are null.");
+
+        final ValidatorResult result = results.getValidatorResult("value");
+
+        assertNotNull(result, () -> ACTION + " value ValidatorResult should not be null.");
+        assertTrue(result.containsAction(ACTION), () -> "Value " + info.getValue() + " ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(passed ? result.isValid(ACTION) : !result.isValid(ACTION),
+                () -> "Value " + info.getValue() + "ValidatorResult for the '" + ACTION + "' action should have " + (passed ? "passed" : "failed") + ".");
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/EntityImportTest.java b/src/test/java/org/apache/commons/validator/EntityImportTest.java
index b6a0c4b..ab34f53 100644
--- a/src/test/java/org/apache/commons/validator/EntityImportTest.java
+++ b/src/test/java/org/apache/commons/validator/EntityImportTest.java
@@ -16,34 +16,35 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
 import java.net.URL;
 import java.util.Locale;
 
+import org.junit.jupiter.api.Test;
 
 /**
  * Tests entity imports.
  */
 public class EntityImportTest extends AbstractCommonTest {
 
-    public EntityImportTest(final String name) {
-        super(name);
-    }
-
     /**
      * Tests the entity import loading the <code>byteForm</code> form.
      */
+    @Test
     public void testEntityImport() throws Exception {
         final URL url = getClass().getResource("EntityImportTest-config.xml");
         final ValidatorResources resources = new ValidatorResources(url.toExternalForm());
-        assertNotNull("Form should be found", resources.getForm(Locale.getDefault(), "byteForm"));
+        assertNotNull(resources.getForm(Locale.getDefault(), "byteForm"), "Form should be found");
     }
 
     /**
      * Tests loading ValidatorResources from a URL
      */
+    @Test
     public void testParseURL() throws Exception {
         final URL url = getClass().getResource("EntityImportTest-config.xml");
         final ValidatorResources resources = new ValidatorResources(url);
-        assertNotNull("Form should be found", resources.getForm(Locale.getDefault(), "byteForm"));
+        assertNotNull(resources.getForm(Locale.getDefault(), "byteForm"), "Form should be found");
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/ExceptionTest.java b/src/test/java/org/apache/commons/validator/ExceptionTest.java
index d195cf0..ec39c66 100644
--- a/src/test/java/org/apache/commons/validator/ExceptionTest.java
+++ b/src/test/java/org/apache/commons/validator/ExceptionTest.java
@@ -16,8 +16,13 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.io.IOException;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
 /**
@@ -26,8 +31,7 @@
 public class ExceptionTest extends AbstractCommonTest {
 
     /**
-     * The key used to retrieve the set of validation
-     * rules from the xml file.
+     * The key used to retrieve the set of validation rules from the xml file.
      */
     protected static String FORM_KEY = "exceptionForm";
 
@@ -36,23 +40,18 @@
      */
     protected static String ACTION = "raiseException";
 
-    public ExceptionTest(final String name) {
-        super(name);
-    }
-
     /**
-     * Load <code>ValidatorResources</code> from
-     * validator-exception.xml.
+     * Load <code>ValidatorResources</code> from validator-exception.xml.
      */
-    @Override
+    @BeforeEach
     protected void setUp() throws IOException, SAXException {
         loadResources("ExceptionTest-config.xml");
     }
 
     /**
-     * Tests handling of checked exceptions - should become
-     * ValidatorExceptions.
+     * Tests handling of checked exceptions - should become ValidatorExceptions.
      */
+    @Test
     public void testValidatorException() {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -75,44 +74,10 @@
     }
 
     /**
-     * Tests handling of runtime exceptions.
+     * Tests handling of checked exceptions - should become ValidatorExceptions.
      *
-     * N.B. This test has been removed (renamed) as it currently
-     *      serves no purpose. If/When exception handling
-     *      is changed in Validator 2.0 it can be reconsidered
-     *      then.
-     */
-    public void XtestRuntimeException() throws ValidatorException {
-        // Create bean to run test on.
-        final ValueBean info = new ValueBean();
-        info.setValue("RUNTIME");
-
-        // Construct validator based on the loaded resources
-        // and the form key
-        final Validator validator = new Validator(resources, FORM_KEY);
-        // add the name bean to the validator as a resource
-        // for the validations to be performed on.
-        validator.setParameter(Validator.BEAN_PARAM, info);
-
-        // Get results of the validation which can throw ValidatorException
-        try {
-            validator.validate();
-            //fail("RuntimeException should occur here!");
-        } catch (final RuntimeException expected) {
-            fail("RuntimeExceptions should be treated as validation failures in Validator 1.x.");
-            // This will be true in Validator 2.0
-            //assertTrue("RUNTIME-EXCEPTION".equals(expected.getMessage()));
-        }
-    }
-
-    /**
-     * Tests handling of checked exceptions - should become
-     * ValidatorExceptions.
-     *
-     * N.B. This test has been removed (renamed) as it currently
-     *      serves no purpose. If/When exception handling
-     *      is changed in Validator 2.0 it can be reconsidered
-     *      then.
+     * N.B. This test has been removed (renamed) as it currently serves no purpose. If/When exception handling is changed in Validator 2.0 it can be
+     * reconsidered then.
      */
     public void XtestCheckedException() {
         // Create bean to run test on.
@@ -145,4 +110,33 @@
 //            assertTrue("CHECKED-EXCEPTION".equals(expected.getMessage()));
 //        }
     }
+
+    /**
+     * Tests handling of runtime exceptions.
+     *
+     * N.B. This test has been removed (renamed) as it currently serves no purpose. If/When exception handling is changed in Validator 2.0 it can be
+     * reconsidered then.
+     */
+    public void XtestRuntimeException() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+        info.setValue("RUNTIME");
+
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, info);
+
+        // Get results of the validation which can throw ValidatorException
+        try {
+            validator.validate();
+            // fail("RuntimeException should occur here!");
+        } catch (final RuntimeException expected) {
+            fail("RuntimeExceptions should be treated as validation failures in Validator 1.x.");
+            // This will be true in Validator 2.0
+            // assertTrue("RUNTIME-EXCEPTION".equals(expected.getMessage()));
+        }
+    }
 }
diff --git a/src/test/java/org/apache/commons/validator/ExtensionTest.java b/src/test/java/org/apache/commons/validator/ExtensionTest.java
index 5b71ed4..1c2a1bc 100644
--- a/src/test/java/org/apache/commons/validator/ExtensionTest.java
+++ b/src/test/java/org/apache/commons/validator/ExtensionTest.java
@@ -16,59 +16,54 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.InputStream;
 
-import junit.framework.TestCase;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
- * <p>Performs tests for extension in form definitions. Performs the same tests
- * RequiredNameTest does but with an equivalent validation definition with extension
- * definitions (validator-extension.xml), plus an extra check on overriding rules and
- * another one checking it mantains correct order when extending.</p>
+ * <p>
+ * Performs tests for extension in form definitions. Performs the same tests RequiredNameTest does but with an equivalent validation definition with extension
+ * definitions (validator-extension.xml), plus an extra check on overriding rules and another one checking it mantains correct order when extending.
+ * </p>
  */
-public class ExtensionTest extends TestCase {
+public class ExtensionTest {
 
     /**
-     * The key used to retrieve the set of validation
-     * rules from the xml file.
-    */
+     * The key used to retrieve the set of validation rules from the xml file.
+     */
     protected static String FORM_KEY = "nameForm";
 
     /**
-     * The key used to retrieve the set of validation
-     * rules from the xml file.
-    */
+     * The key used to retrieve the set of validation rules from the xml file.
+     */
     protected static String FORM_KEY2 = "nameForm2";
 
     /**
-     * The key used to retrieve the set of validation
-     * rules from the xml file.
-    */
+     * The key used to retrieve the set of validation rules from the xml file.
+     */
     protected static String CHECK_MSG_KEY = "nameForm.lastname.displayname";
 
     /**
      * The key used to retrieve the validator action.
-    */
+     */
     protected static String ACTION = "required";
 
     /**
      * Resources used for validation tests.
-    */
+     */
     private ValidatorResources resources;
 
     /**
-     * Constructor de ExtensionTest.
-     * @param arg0
+     * Load <code>ValidatorResources</code> from validator-extension.xml.
      */
-    public ExtensionTest(final String arg0) {
-        super(arg0);
-    }
-
-    /**
-     * Load <code>ValidatorResources</code> from
-     * validator-extension.xml.
-    */
-    @Override
+    @BeforeEach
     protected void setUp() throws Exception {
         // Load resources
         try (InputStream in = this.getClass().getResourceAsStream("ExtensionTest-config.xml")) {
@@ -76,267 +71,272 @@
         }
     }
 
-    @Override
+    @AfterEach
     protected void tearDown() {
     }
 
     /**
-     * Tests the required validation failure.
-    */
-    public void testRequired() throws ValidatorException {
-       // Create bean to run test on.
-       final NameBean name = new NameBean();
+     * Tests if the order is mantained when extending a form. Parent form fields should preceed self form fields, except if we override the rules.
+     */
+    @Test
+    public void testOrder() {
 
-       // Construct validator based on the loaded resources
-       // and the form key
-       final Validator validator = new Validator(resources, FORM_KEY);
-       // add the name bean to the validator as a resource
-       // for the validations to be performed on.
-       validator.setParameter(Validator.BEAN_PARAM, name);
+        final Form form = resources.getForm(ValidatorResources.defaultLocale, FORM_KEY);
+        final Form form2 = resources.getForm(ValidatorResources.defaultLocale, FORM_KEY2);
 
-       // Get results of the validation.
-       // throws ValidatorException,
-       // but we aren't catching for testing
-       // since no validation methods we use
-       // throw this
-       final ValidatorResults results = validator.validate();
+        assertNotNull(form, FORM_KEY + " is null.");
+        assertEquals(2, form.getFields().size(), "There should only be 2 fields in " + FORM_KEY);
 
-       assertNotNull("Results are null.", results);
+        assertNotNull(form2, FORM_KEY2 + " is null.");
+        assertEquals(2, form2.getFields().size(), "There should only be 2 fields in " + FORM_KEY2);
 
-       final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-       final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        // get the first field
+        Field fieldFirstName = form.getFields().get(0);
+        // get the second field
+        Field fieldLastName = form.getFields().get(1);
+        assertTrue(fieldFirstName.getKey().equals("firstName"), "firstName in " + FORM_KEY + " should be the first in the list");
+        assertTrue(fieldLastName.getKey().equals("lastName"), "lastName in " + FORM_KEY + " should be the first in the list");
 
-       assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-       assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-       assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have failed.", !firstNameResult.isValid(ACTION));
+//     get the second field
+        fieldLastName = form2.getFields().get(0);
+        // get the first field
+        fieldFirstName = form2.getFields().get(1);
+        assertTrue(fieldFirstName.getKey().equals("firstName"), "firstName in " + FORM_KEY2 + " should be the first in the list");
+        assertTrue(fieldLastName.getKey().equals("lastName"), "lastName in " + FORM_KEY2 + " should be the first in the list");
 
-       assertNotNull("First Name ValidatorResult should not be null.", lastNameResult);
-       assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-       assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have failed.", !lastNameResult.isValid(ACTION));
     }
 
     /**
-     * Tests the required validation for first name if it is blank.
-    */
-    public void testRequiredFirstNameBlank() throws ValidatorException {
-       // Create bean to run test on.
-       final NameBean name = new NameBean();
-       name.setFirstName("");
+     * Tests if we can override a rule. We "can" override a rule if the message shown when the firstName required test fails and the lastName test is null.
+     */
+    @Test
+    public void testOverrideRule() throws ValidatorException {
 
-       // Construct validator based on the loaded resources
-       // and the form key
-       final Validator validator = new Validator(resources, FORM_KEY);
-       // add the name bean to the validator as a resource
-       // for the validations to be performed on.
-       validator.setParameter(Validator.BEAN_PARAM, name);
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setLastName("Smith");
 
-       // Get results of the validation.
-       final ValidatorResults results = validator.validate();
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY2);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-       assertNotNull("Results are null.", results);
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-       final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-       final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(results, "Results are null.");
 
-       assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-       assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-       assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have failed.", !firstNameResult.isValid(ACTION));
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.field.getArg(0).getKey().equals(CHECK_MSG_KEY),
+                "First Name ValidatorResult for the '" + ACTION + "' action should have '" + CHECK_MSG_KEY + " as a key.");
 
-       assertNotNull("First Name ValidatorResult should not be null.", lastNameResult);
-       assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-       assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have failed.", !lastNameResult.isValid(ACTION));
+        assertNull(lastNameResult, "Last Name ValidatorResult should be null.");
+    }
+
+    /**
+     * Tests the required validation failure.
+     */
+    @Test
+    public void testRequired() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
+
+        // Get results of the validation.
+        // throws ValidatorException,
+        // but we aren't catching for testing
+        // since no validation methods we use
+        // throw this
+        final ValidatorResults results = validator.validate();
+
+        assertNotNull(results, "Results are null.");
+
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!firstNameResult.isValid(ACTION), "First Name ValidatorResult for the '" + ACTION + "' action should have failed.");
+
+        assertNotNull(lastNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!lastNameResult.isValid(ACTION), "Last Name ValidatorResult for the '" + ACTION + "' action should have failed.");
     }
 
     /**
      * Tests the required validation for first name.
-    */
+     */
+    @Test
     public void testRequiredFirstName() throws ValidatorException {
-       // Create bean to run test on.
-       final NameBean name = new NameBean();
-       name.setFirstName("Joe");
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("Joe");
 
-       // Construct validator based on the loaded resources
-       // and the form key
-       final Validator validator = new Validator(resources, FORM_KEY);
-       // add the name bean to the validator as a resource
-       // for the validations to be performed on.
-       validator.setParameter(Validator.BEAN_PARAM, name);
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-       // Get results of the validation.
-       final ValidatorResults results = validator.validate();
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-       assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
-       final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-       final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-       assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-       assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-       assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have passed.", firstNameResult.isValid(ACTION));
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(firstNameResult.isValid(ACTION), "First Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-       assertNotNull("First Name ValidatorResult should not be null.", lastNameResult);
-       assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-       assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have failed.", !lastNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!lastNameResult.isValid(ACTION), "Last Name ValidatorResult for the '" + ACTION + "' action should have failed.");
     }
 
     /**
-     * Tests the required validation for last name if it is blank.
-    */
-    public void testRequiredLastNameBlank() throws ValidatorException {
-       // Create bean to run test on.
-       final NameBean name = new NameBean();
-       name.setLastName("");
+     * Tests the required validation for first name if it is blank.
+     */
+    @Test
+    public void testRequiredFirstNameBlank() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("");
 
-       // Construct validator based on the loaded resources
-       // and the form key
-       final Validator validator = new Validator(resources, FORM_KEY);
-       // add the name bean to the validator as a resource
-       // for the validations to be performed on.
-       validator.setParameter(Validator.BEAN_PARAM, name);
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-       // Get results of the validation.
-       final ValidatorResults results = validator.validate();
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-       assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
-       final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-       final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-       assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-       assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-       assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have failed.", !firstNameResult.isValid(ACTION));
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!firstNameResult.isValid(ACTION), "First Name ValidatorResult for the '" + ACTION + "' action should have failed.");
 
-       assertNotNull("First Name ValidatorResult should not be null.", lastNameResult);
-       assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-       assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have failed.", !lastNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!lastNameResult.isValid(ACTION), "Last Name ValidatorResult for the '" + ACTION + "' action should have failed.");
     }
 
     /**
      * Tests the required validation for last name.
-    */
+     */
+    @Test
     public void testRequiredLastName() throws ValidatorException {
-       // Create bean to run test on.
-       final NameBean name = new NameBean();
-       name.setLastName("Smith");
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setLastName("Smith");
 
-       // Construct validator based on the loaded resources
-       // and the form key
-       final Validator validator = new Validator(resources, FORM_KEY);
-       // add the name bean to the validator as a resource
-       // for the validations to be performed on.
-       validator.setParameter(Validator.BEAN_PARAM, name);
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-       // Get results of the validation.
-       final ValidatorResults results = validator.validate();
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-       assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
-       final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-       final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-       assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-       assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-       assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have failed.", !firstNameResult.isValid(ACTION));
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!firstNameResult.isValid(ACTION), "First Name ValidatorResult for the '" + ACTION + "' action should have failed.");
 
-       assertNotNull("First Name ValidatorResult should not be null.", lastNameResult);
-       assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-       assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have passed.", lastNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(lastNameResult.isValid(ACTION), "Last Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
     }
 
     /**
+     * Tests the required validation for last name if it is blank.
+     */
+    @Test
+    public void testRequiredLastNameBlank() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setLastName("");
+
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
+
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
+
+        assertNotNull(results, "Results are null.");
+
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!firstNameResult.isValid(ACTION), "First Name ValidatorResult for the '" + ACTION + "' action should have failed.");
+
+        assertNotNull(lastNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!lastNameResult.isValid(ACTION), "Last Name ValidatorResult for the '" + ACTION + "' action should have failed.");
+    }
+
+    /**
      * Tests the required validation for first and last name.
-    */
+     */
+    @Test
     public void testRequiredName() throws ValidatorException {
-       // Create bean to run test on.
-       final NameBean name = new NameBean();
-       name.setFirstName("Joe");
-       name.setLastName("Smith");
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("Joe");
+        name.setLastName("Smith");
 
-       // Construct validator based on the loaded resources
-       // and the form key
-       final Validator validator = new Validator(resources, FORM_KEY);
-       // add the name bean to the validator as a resource
-       // for the validations to be performed on.
-       validator.setParameter(Validator.BEAN_PARAM, name);
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-       // Get results of the validation.
-       final ValidatorResults results = validator.validate();
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-       assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
-       final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-       final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-       assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-       assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-       assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have passed.", firstNameResult.isValid(ACTION));
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(firstNameResult.isValid(ACTION), "First Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-       assertNotNull("Last Name ValidatorResult should not be null.", lastNameResult);
-       assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-       assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have passed.", lastNameResult.isValid(ACTION));
-    }
-
-
-    /**
-     * Tests if we can override a rule. We "can" override a rule if the message shown
-     * when the firstName required test fails and the lastName test is null.
-    */
-    public void testOverrideRule() throws ValidatorException {
-
-       // Create bean to run test on.
-       final NameBean name = new NameBean();
-       name.setLastName("Smith");
-
-       // Construct validator based on the loaded resources
-       // and the form key
-       final Validator validator = new Validator(resources, FORM_KEY2);
-       // add the name bean to the validator as a resource
-       // for the validations to be performed on.
-       validator.setParameter(Validator.BEAN_PARAM, name);
-
-       // Get results of the validation.
-       final ValidatorResults results = validator.validate();
-
-       assertNotNull("Results are null.", results);
-
-       final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-       final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
-       assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-       assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have '" + CHECK_MSG_KEY + " as a key.", firstNameResult.field.getArg(0).getKey().equals(CHECK_MSG_KEY));
-
-       assertNull("Last Name ValidatorResult should be null.", lastNameResult);
-    }
-
-
-    /**
-     * Tests if the order is mantained when extending a form. Parent form fields should
-     * preceed self form fields, except if we override the rules.
-    */
-    public void testOrder() {
-
-       final Form form = resources.getForm(ValidatorResources.defaultLocale, FORM_KEY);
-       final Form form2 = resources.getForm(ValidatorResources.defaultLocale, FORM_KEY2);
-
-       assertNotNull(FORM_KEY + " is null.", form);
-       assertTrue("There should only be 2 fields in " + FORM_KEY, form.getFields().size() == 2);
-
-       assertNotNull(FORM_KEY2 + " is null.", form2);
-       assertTrue("There should only be 2 fields in " + FORM_KEY2, form2.getFields().size() == 2);
-
-       //get the first field
-       Field fieldFirstName = form.getFields().get(0);
-       //get the second field
-       Field fieldLastName = form.getFields().get(1);
-       assertTrue("firstName in " + FORM_KEY + " should be the first in the list", fieldFirstName.getKey().equals("firstName"));
-       assertTrue("lastName in " + FORM_KEY + " should be the first in the list", fieldLastName.getKey().equals("lastName"));
-
-//     get the second field
-       fieldLastName = form2.getFields().get(0);
-        //get the first field
-        fieldFirstName = form2.getFields().get(1);
-        assertTrue("firstName in " + FORM_KEY2 + " should be the first in the list", fieldFirstName.getKey().equals("firstName"));
-       assertTrue("lastName in " + FORM_KEY2 + " should be the first in the list", fieldLastName.getKey().equals("lastName"));
-
+        assertNotNull(lastNameResult, "Last Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(lastNameResult.isValid(ACTION), "Last Name ValidatorResult for the '" + ACTION + "' action should have passed.");
     }
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/FieldTest.java b/src/test/java/org/apache/commons/validator/FieldTest.java
index 35b8baa..83d8288 100644
--- a/src/test/java/org/apache/commons/validator/FieldTest.java
+++ b/src/test/java/org/apache/commons/validator/FieldTest.java
@@ -16,235 +16,21 @@
  */
 package org.apache.commons.validator;
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * Test <code>Field</code> objects.
  */
-public class FieldTest extends TestCase {
-
+public class FieldTest {
 
     protected Field field;
 
     /**
-     * FieldTest constructor.
-     */
-    public FieldTest() {
-    }
-
-    /**
-     * FieldTest constructor.
-     * @param name
-     */
-    public FieldTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Test setup
-     */
-    @Override
-    public void setUp() {
-        field = new Field();
-    }
-
-    /**
-     * Test clean up
-     */
-    @Override
-    public void tearDown() {
-        field = null;
-    }
-
-    /**
-     * test Field with no arguments
-     */
-    public void testEmptyArgs() {
-
-        assertEquals("Empty Args(1) ", 0, field.getArgs("required").length);
-
-    }
-    /**
-     * test Field with only 'default' arguments, no positions specified.
-     */
-    public void testDefaultPositionImplied() {
-
-        field.addArg(createArg("default-position-0"));
-        field.addArg(createArg("default-position-1"));
-        field.addArg(createArg("default-position-2"));
-
-        assertEquals("testDefaultPositionImplied(1) ", 3, field.getArgs("required").length);
-        assertEquals("testDefaultPositionImplied(2) ", "default-position-0", field.getArg("required", 0).getKey());
-        assertEquals("testDefaultPositionImplied(3) ", "default-position-1", field.getArg("required", 1).getKey());
-        assertEquals("testDefaultPositionImplied(4) ", "default-position-2", field.getArg("required", 2).getKey());
-
-    }
-
-    /**
-     * test Field with only 'default' arguments, positions specified.
-     */
-    public void testDefaultUsingPositions() {
-
-        field.addArg(createArg("default-position-1", 1));
-        field.addArg(createArg("default-position-0", 0));
-        field.addArg(createArg("default-position-2", 2));
-
-        assertEquals("testDefaultUsingPositions(1) ", 3, field.getArgs("required").length);
-        assertEquals("testDefaultUsingPositions(2) ", "default-position-0", field.getArg("required", 0).getKey());
-        assertEquals("testDefaultUsingPositions(3) ", "default-position-1", field.getArg("required", 1).getKey());
-        assertEquals("testDefaultUsingPositions(4) ", "default-position-2", field.getArg("required", 2).getKey());
-
-    }
-
-    /**
-     * test Field with only 'default' arguments, position specified for one argument
-     */
-    public void testDefaultOnePosition() {
-
-        field.addArg(createArg("default-position-0"));
-        field.addArg(createArg("default-position-2", 2));
-        field.addArg(createArg("default-position-3"));
-
-        assertEquals("testDefaultOnePosition(1) ", 4, field.getArgs("required").length);
-        assertEquals("testDefaultOnePosition(2) ", "default-position-0", field.getArg("required", 0).getKey());
-        assertNull("testDefaultOnePosition(3) ", field.getArg("required", 1));
-        assertEquals("testDefaultOnePosition(4) ", "default-position-2", field.getArg("required", 2).getKey());
-        assertEquals("testDefaultOnePosition(5) ", "default-position-3", field.getArg("required", 3).getKey());
-
-    }
-
-    /**
-     * test Field with only 'default' arguments, some position specified.
-     */
-    public void testDefaultSomePositions() {
-
-        field.addArg(createArg("default-position-0"));
-        field.addArg(createArg("default-position-2", 2));
-        field.addArg(createArg("default-position-3"));
-        field.addArg(createArg("default-position-1", 1));
-
-        assertEquals("testDefaultSomePositions(1) ", 4, field.getArgs("required").length);
-        assertEquals("testDefaultSomePositions(2) ", "default-position-0", field.getArg("required", 0).getKey());
-        assertEquals("testDefaultSomePositions(3) ", "default-position-1", field.getArg("required", 1).getKey());
-        assertEquals("testDefaultSomePositions(4) ", "default-position-2", field.getArg("required", 2).getKey());
-        assertEquals("testDefaultSomePositions(5) ", "default-position-3", field.getArg("required", 3).getKey());
-
-    }
-
-    /**
-     * test Field with a 'default' argument overriden using 'position' property
-     */
-    public void testOverrideUsingPositionA() {
-
-        field.addArg(createArg("default-position-0"));
-        field.addArg(createArg("default-position-1"));
-        field.addArg(createArg("default-position-2"));
-        field.addArg(createArg("required-position-1", "required", 1));
-
-        // use 'required' as name
-        assertEquals("testOverrideUsingPositionA(1) ", 3, field.getArgs("required").length);
-        assertEquals("testOverrideUsingPositionA(2) ", "required-position-1", field.getArg("required", 1).getKey());
-
-        // use 'mask' as name
-        assertEquals("testOverrideUsingPositionA(3) ", 3, field.getArgs("mask").length);
-        assertEquals("testOverrideUsingPositionA(4) ", "default-position-1", field.getArg("mask", 1).getKey());
-
-        // Get Default
-        assertEquals("testOverrideUsingPositionA(5) ", "default-position-1", field.getArg(1).getKey());
-
-    }
-
-    /**
-     * test Field with a 'default' argument overriden using 'position' property
-     */
-    public void testOverrideUsingPositionB() {
-
-        field.addArg(createArg("required-position-3", "required", 3));
-        field.addArg(createArg("required-position-1", "required", 1));
-        field.addArg(createArg("default-position-0"));
-        field.addArg(createArg("default-position-1"));
-        field.addArg(createArg("default-position-2"));
-
-        // use 'required' as name
-        assertEquals("testOverrideUsingPositionB(1) ", 4, field.getArgs("required").length);
-        assertEquals("testOverrideUsingPositionB(2) ", "default-position-0",  field.getArg("required", 0).getKey());
-        assertEquals("testOverrideUsingPositionB(3) ", "required-position-1", field.getArg("required", 1).getKey());
-        assertEquals("testOverrideUsingPositionB(4) ", "default-position-2",  field.getArg("required", 2).getKey());
-        assertEquals("testOverrideUsingPositionB(5) ", "required-position-3", field.getArg("required", 3).getKey());
-
-        // use 'mask' as name
-        assertEquals("testOverrideUsingPositionB(6) ", 4, field.getArgs("mask").length);
-        assertEquals("testOverrideUsingPositionB(6) ", "default-position-0", field.getArg("mask", 0).getKey());
-        assertEquals("testOverrideUsingPositionB(7) ", "default-position-1", field.getArg("mask", 1).getKey());
-        assertEquals("testOverrideUsingPositionB(8) ", "default-position-2", field.getArg("mask", 2).getKey());
-        assertNull("testOverrideUsingPositionB(9) ", field.getArg("mask", 3));
-
-    }
-
-    /**
-     * test Field with a 'default' argument overriden without positions specified.
-     */
-    public void testOverridePositionImplied() {
-
-        field.addArg(createArg("default-position-0"));
-        field.addArg(createArg("required-position-1", "required"));
-        field.addArg(createArg("required-position-2", "required"));
-        field.addArg(createArg("mask-position-1", "mask"));
-
-        // use 'required' as name
-        assertEquals("testOverridePositionImplied(1) ", 3, field.getArgs("required").length);
-        assertEquals("testOverridePositionImplied(2) ", "default-position-0", field.getArg("required", 0).getKey());
-        assertEquals("testOverridePositionImplied(3) ", "required-position-1", field.getArg("required", 1).getKey());
-        assertEquals("testOverridePositionImplied(4) ", "required-position-2", field.getArg("required", 2).getKey());
-
-        // use 'mask' as name
-        assertEquals("testOverridePositionImplied(5) ", 3, field.getArgs("mask").length);
-        assertEquals("testOverridePositionImplied(6) ", "default-position-0", field.getArg("mask", 0).getKey());
-        assertEquals("testOverridePositionImplied(7) ", "mask-position-1", field.getArg("mask", 1).getKey());
-        assertNull("testOverridePositionImplied(8) ", field.getArg("mask", 2));
-
-        // Get Defaults
-        assertEquals("testOverridePositionImplied(9) ",  "default-position-0", field.getArg(0).getKey());
-        assertNull("testOverridePositionImplied(10) ", field.getArg(1));
-        assertNull("testOverridePositionImplied(11) ", field.getArg(2));
-
-    }
-
-    /**
-     * test Field with a 'default' argument overriden with some positions specified
-     */
-    public void testOverrideSomePosition() {
-
-        field.addArg(createArg("default-position-0"));
-        field.addArg(createArg("default-position-1"));
-        field.addArg(createArg("default-position-2"));
-        field.addArg(createArg("required-position-1", "required", 1));
-        field.addArg(createArg("required-position-2", "required"));
-        field.addArg(createArg("mask-position-3", "mask"));
-
-        // use 'required' as name
-        assertEquals("testOverrideSomePosition(1) ", 4, field.getArgs("required").length);
-        assertEquals("testOverrideSomePosition(2) ", "default-position-0", field.getArg("required", 0).getKey());
-        assertEquals("testOverrideSomePosition(3) ", "required-position-1", field.getArg("required", 1).getKey());
-        assertEquals("testOverrideSomePosition(4) ", "required-position-2", field.getArg("required", 2).getKey());
-        assertNull("testOverrideSomePosition(5) ", field.getArg("required", 3));
-
-        // use 'mask' as name
-        assertEquals("testOverrideSomePosition(6) ", 4, field.getArgs("mask").length);
-        assertEquals("testOverrideSomePosition(7) ", "default-position-0", field.getArg("mask", 0).getKey());
-        assertEquals("testOverrideSomePosition(8) ", "default-position-1", field.getArg("mask", 1).getKey());
-        assertEquals("testOverrideSomePosition(9) ", "default-position-2", field.getArg("mask", 2).getKey());
-        assertEquals("testOverrideSomePosition(10) ", "mask-position-3", field.getArg("mask", 3).getKey());
-
-        // Get Defaults
-        assertEquals("testOverrideSomePosition(11) ",  "default-position-0", field.getArg(0).getKey());
-        assertEquals("testOverrideSomePosition(12) ", "default-position-1", field.getArg(1).getKey());
-        assertEquals("testOverrideSomePosition(13) ", "default-position-2", field.getArg(2).getKey());
-        assertNull("testOverrideSomePosition(14) ", field.getArg(3));
-
-    }
-
-    /**
      * Convenience Method - create argument (no name or position specified)
      */
     private Arg createArg(final String key) {
@@ -280,4 +66,218 @@
         return arg;
     }
 
+    /**
+     * Test setup
+     */
+    @BeforeEach
+    public void setUp() {
+        field = new Field();
+    }
+
+    /**
+     * Test clean up
+     */
+    @AfterEach
+    public void tearDown() {
+        field = null;
+    }
+
+    /**
+     * test Field with only 'default' arguments, position specified for one argument
+     */
+    @Test
+    public void testDefaultOnePosition() {
+
+        field.addArg(createArg("default-position-0"));
+        field.addArg(createArg("default-position-2", 2));
+        field.addArg(createArg("default-position-3"));
+
+        assertEquals(4, field.getArgs("required").length, "testDefaultOnePosition(1) ");
+        assertEquals("default-position-0", field.getArg("required", 0).getKey(), "testDefaultOnePosition(2) ");
+        assertNull(field.getArg("required", 1), "testDefaultOnePosition(3) ");
+        assertEquals("default-position-2", field.getArg("required", 2).getKey(), "testDefaultOnePosition(4) ");
+        assertEquals("default-position-3", field.getArg("required", 3).getKey(), "testDefaultOnePosition(5) ");
+
+    }
+
+    /**
+     * test Field with only 'default' arguments, no positions specified.
+     */
+    @Test
+    public void testDefaultPositionImplied() {
+
+        field.addArg(createArg("default-position-0"));
+        field.addArg(createArg("default-position-1"));
+        field.addArg(createArg("default-position-2"));
+
+        assertEquals(3, field.getArgs("required").length, "testDefaultPositionImplied(1) ");
+        assertEquals("default-position-0", field.getArg("required", 0).getKey(), "testDefaultPositionImplied(2) ");
+        assertEquals("default-position-1", field.getArg("required", 1).getKey(), "testDefaultPositionImplied(3) ");
+        assertEquals("default-position-2", field.getArg("required", 2).getKey(), "testDefaultPositionImplied(4) ");
+
+    }
+
+    /**
+     * test Field with only 'default' arguments, some position specified.
+     */
+    @Test
+    public void testDefaultSomePositions() {
+
+        field.addArg(createArg("default-position-0"));
+        field.addArg(createArg("default-position-2", 2));
+        field.addArg(createArg("default-position-3"));
+        field.addArg(createArg("default-position-1", 1));
+
+        assertEquals(4, field.getArgs("required").length, "testDefaultSomePositions(1) ");
+        assertEquals("default-position-0", field.getArg("required", 0).getKey(), "testDefaultSomePositions(2) ");
+        assertEquals("default-position-1", field.getArg("required", 1).getKey(), "testDefaultSomePositions(3) ");
+        assertEquals("default-position-2", field.getArg("required", 2).getKey(), "testDefaultSomePositions(4) ");
+        assertEquals("default-position-3", field.getArg("required", 3).getKey(), "testDefaultSomePositions(5) ");
+
+    }
+
+    /**
+     * test Field with only 'default' arguments, positions specified.
+     */
+    @Test
+    public void testDefaultUsingPositions() {
+
+        field.addArg(createArg("default-position-1", 1));
+        field.addArg(createArg("default-position-0", 0));
+        field.addArg(createArg("default-position-2", 2));
+
+        assertEquals(3, field.getArgs("required").length, "testDefaultUsingPositions(1) ");
+        assertEquals("default-position-0", field.getArg("required", 0).getKey(), "testDefaultUsingPositions(2) ");
+        assertEquals("default-position-1", field.getArg("required", 1).getKey(), "testDefaultUsingPositions(3) ");
+        assertEquals("default-position-2", field.getArg("required", 2).getKey(), "testDefaultUsingPositions(4) ");
+
+    }
+
+    /**
+     * test Field with no arguments
+     */
+    @Test
+    public void testEmptyArgs() {
+
+        assertEquals(0, field.getArgs("required").length, "Empty Args(1) ");
+
+    }
+
+    /**
+     * test Field with a 'default' argument overriden without positions specified.
+     */
+    @Test
+    public void testOverridePositionImplied() {
+
+        field.addArg(createArg("default-position-0"));
+        field.addArg(createArg("required-position-1", "required"));
+        field.addArg(createArg("required-position-2", "required"));
+        field.addArg(createArg("mask-position-1", "mask"));
+
+        // use 'required' as name
+        assertEquals(3, field.getArgs("required").length, "testOverridePositionImplied(1) ");
+        assertEquals("default-position-0", field.getArg("required", 0).getKey(), "testOverridePositionImplied(2) ");
+        assertEquals("required-position-1", field.getArg("required", 1).getKey(), "testOverridePositionImplied(3) ");
+        assertEquals("required-position-2", field.getArg("required", 2).getKey(), "testOverridePositionImplied(4) ");
+
+        // use 'mask' as name
+        assertEquals(3, field.getArgs("mask").length, "testOverridePositionImplied(5) ");
+        assertEquals("default-position-0", field.getArg("mask", 0).getKey(), "testOverridePositionImplied(6) ");
+        assertEquals("mask-position-1", field.getArg("mask", 1).getKey(), "testOverridePositionImplied(7) ");
+        assertNull(field.getArg("mask", 2), "testOverridePositionImplied(8) ");
+
+        // Get Defaults
+        assertEquals("default-position-0", field.getArg(0).getKey(), "testOverridePositionImplied(9) ");
+        assertNull(field.getArg(1), "testOverridePositionImplied(10) ");
+        assertNull(field.getArg(2), "testOverridePositionImplied(11) ");
+
+    }
+
+    /**
+     * test Field with a 'default' argument overriden with some positions specified
+     */
+    @Test
+    public void testOverrideSomePosition() {
+
+        field.addArg(createArg("default-position-0"));
+        field.addArg(createArg("default-position-1"));
+        field.addArg(createArg("default-position-2"));
+        field.addArg(createArg("required-position-1", "required", 1));
+        field.addArg(createArg("required-position-2", "required"));
+        field.addArg(createArg("mask-position-3", "mask"));
+
+        // use 'required' as name
+        assertEquals(4, field.getArgs("required").length, "testOverrideSomePosition(1) ");
+        assertEquals("default-position-0", field.getArg("required", 0).getKey(), "testOverrideSomePosition(2) ");
+        assertEquals("required-position-1", field.getArg("required", 1).getKey(), "testOverrideSomePosition(3) ");
+        assertEquals("required-position-2", field.getArg("required", 2).getKey(), "testOverrideSomePosition(4) ");
+        assertNull(field.getArg("required", 3), "testOverrideSomePosition(5) ");
+
+        // use 'mask' as name
+        assertEquals(4, field.getArgs("mask").length, "testOverrideSomePosition(6) ");
+        assertEquals("default-position-0", field.getArg("mask", 0).getKey(), "testOverrideSomePosition(7) ");
+        assertEquals("default-position-1", field.getArg("mask", 1).getKey(), "testOverrideSomePosition(8) ");
+        assertEquals("default-position-2", field.getArg("mask", 2).getKey(), "testOverrideSomePosition(9) ");
+        assertEquals("mask-position-3", field.getArg("mask", 3).getKey(), "testOverrideSomePosition(10) ");
+
+        // Get Defaults
+        assertEquals("default-position-0", field.getArg(0).getKey(), "testOverrideSomePosition(11) ");
+        assertEquals("default-position-1", field.getArg(1).getKey(), "testOverrideSomePosition(12) ");
+        assertEquals("default-position-2", field.getArg(2).getKey(), "testOverrideSomePosition(13) ");
+        assertNull(field.getArg(3), "testOverrideSomePosition(14) ");
+
+    }
+
+    /**
+     * test Field with a 'default' argument overriden using 'position' property
+     */
+    @Test
+    public void testOverrideUsingPositionA() {
+
+        field.addArg(createArg("default-position-0"));
+        field.addArg(createArg("default-position-1"));
+        field.addArg(createArg("default-position-2"));
+        field.addArg(createArg("required-position-1", "required", 1));
+
+        // use 'required' as name
+        assertEquals(3, field.getArgs("required").length, "testOverrideUsingPositionA(1) ");
+        assertEquals("required-position-1", field.getArg("required", 1).getKey(), "testOverrideUsingPositionA(2) ");
+
+        // use 'mask' as name
+        assertEquals(3, field.getArgs("mask").length, "testOverrideUsingPositionA(3) ");
+        assertEquals("default-position-1", field.getArg("mask", 1).getKey(), "testOverrideUsingPositionA(4) ");
+
+        // Get Default
+        assertEquals("default-position-1", field.getArg(1).getKey(), "testOverrideUsingPositionA(5) ");
+
+    }
+
+    /**
+     * test Field with a 'default' argument overriden using 'position' property
+     */
+    @Test
+    public void testOverrideUsingPositionB() {
+
+        field.addArg(createArg("required-position-3", "required", 3));
+        field.addArg(createArg("required-position-1", "required", 1));
+        field.addArg(createArg("default-position-0"));
+        field.addArg(createArg("default-position-1"));
+        field.addArg(createArg("default-position-2"));
+
+        // use 'required' as name
+        assertEquals(4, field.getArgs("required").length, "testOverrideUsingPositionB(1) ");
+        assertEquals("default-position-0", field.getArg("required", 0).getKey(), "testOverrideUsingPositionB(2) ");
+        assertEquals("required-position-1", field.getArg("required", 1).getKey(), "testOverrideUsingPositionB(3) ");
+        assertEquals("default-position-2", field.getArg("required", 2).getKey(), "testOverrideUsingPositionB(4) ");
+        assertEquals("required-position-3", field.getArg("required", 3).getKey(), "testOverrideUsingPositionB(5) ");
+
+        // use 'mask' as name
+        assertEquals(4, field.getArgs("mask").length, "testOverrideUsingPositionB(6) ");
+        assertEquals("default-position-0", field.getArg("mask", 0).getKey(), "testOverrideUsingPositionB(6) ");
+        assertEquals("default-position-1", field.getArg("mask", 1).getKey(), "testOverrideUsingPositionB(7) ");
+        assertEquals("default-position-2", field.getArg("mask", 2).getKey(), "testOverrideUsingPositionB(8) ");
+        assertNull(field.getArg("mask", 3), "testOverrideUsingPositionB(9) ");
+
+    }
+
 }
diff --git a/src/test/java/org/apache/commons/validator/FloatTest.java b/src/test/java/org/apache/commons/validator/FloatTest.java
index 6631bd6..f67ad18 100644
--- a/src/test/java/org/apache/commons/validator/FloatTest.java
+++ b/src/test/java/org/apache/commons/validator/FloatTest.java
@@ -16,14 +16,14 @@
  */
 package org.apache.commons.validator;
 
+import org.junit.jupiter.api.Test;
 
 /**
  * Performs Validation Test for <code>float</code> validations.
  */
 public class FloatTest extends AbstractNumberTest {
 
-    public FloatTest(final String name) {
-        super(name);
+    public FloatTest() {
         ACTION = "float";
         FORM_KEY = "floatForm";
     }
@@ -31,6 +31,7 @@
     /**
      * Tests the float validation.
      */
+    @Test
     public void testFloat() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -40,19 +41,20 @@
     }
 
     /**
-     * Tests the float validation.
+     * Tests the float validation failure.
      */
-    public void testFloatMin() throws ValidatorException {
+    @Test
+    public void testFloatFailure() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
-        info.setValue(Float.toString(Float.MIN_VALUE));
 
-        valueTest(info, true);
+        valueTest(info, false);
     }
 
     /**
      * Tests the float validation.
      */
+    @Test
     public void testFloatMax() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -62,13 +64,15 @@
     }
 
     /**
-     * Tests the float validation failure.
+     * Tests the float validation.
      */
-    public void testFloatFailure() throws ValidatorException {
+    @Test
+    public void testFloatMin() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
+        info.setValue(Float.toString(Float.MIN_VALUE));
 
-        valueTest(info, false);
+        valueTest(info, true);
     }
 
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/GenericTypeValidatorImpl.java b/src/test/java/org/apache/commons/validator/GenericTypeValidatorImpl.java
index 2b90365..9e6c92a 100644
--- a/src/test/java/org/apache/commons/validator/GenericTypeValidatorImpl.java
+++ b/src/test/java/org/apache/commons/validator/GenericTypeValidatorImpl.java
@@ -26,222 +26,194 @@
  */
 public class GenericTypeValidatorImpl {
 
-   /**
-    * Checks if the field can be successfully converted to a <code>byte</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>byte</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Byte validateByte(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+    /**
+     * Checks if the field can be successfully converted to a <code>byte</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>byte</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Byte validateByte(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
 
-      return GenericTypeValidator.formatByte(value);
-   }
+        return GenericTypeValidator.formatByte(value);
+    }
 
-   /**
-    * Checks if the field can be successfully converted to a <code>byte</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>byte</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Byte validateByte(final Object bean, final Field field, final Locale locale) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+    /**
+     * Checks if the field can be successfully converted to a <code>byte</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>byte</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Byte validateByte(final Object bean, final Field field, final Locale locale) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
 
-      return GenericTypeValidator.formatByte(value, locale);
-   }
+        return GenericTypeValidator.formatByte(value, locale);
+    }
 
-   /**
-    * Checks if the field can be successfully converted to a <code>short</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>short</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Short validateShort(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+    /**
+     * Checks if the field can be successfully converted to a <code>date</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>date</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Date validateDate(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+        final String datePattern = field.getVarValue("datePattern");
+        final String datePatternStrict = field.getVarValue("datePatternStrict");
 
-      return GenericTypeValidator.formatShort(value);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>short</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>short</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Short validateShort(final Object bean, final Field field, final Locale locale) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericTypeValidator.formatShort(value, locale);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>int</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>int</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Integer validateInt(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericTypeValidator.formatInt(value);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>int</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>int</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Integer validateInt(final Object bean, final Field field, final Locale locale) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericTypeValidator.formatInt(value, locale);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>long</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>long</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Long validateLong(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericTypeValidator.formatLong(value);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>long</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>long</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Long validateLong(final Object bean, final Field field, final Locale locale) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericTypeValidator.formatLong(value, locale);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>float</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>float</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Float validateFloat(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericTypeValidator.formatFloat(value);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>float</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>float</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Float validateFloat(final Object bean, final Field field, final Locale locale) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericTypeValidator.formatFloat(value, locale);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>double</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>double</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Double validateDouble(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericTypeValidator.formatDouble(value);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>double</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>double</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Double validateDouble(final Object bean, final Field field, final Locale locale) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericTypeValidator.formatDouble(value, locale);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>date</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>date</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Date validateDate(final Object bean, final Field field, final Locale locale) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericTypeValidator.formatDate(value, locale);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>date</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return boolean If the field can be successfully converted
-    * to a <code>date</code> <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static Date validateDate(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-      final String datePattern = field.getVarValue("datePattern");
-      final String datePatternStrict = field.getVarValue("datePatternStrict");
-
-      Date result = null;
-      if (datePattern != null && !datePattern.isEmpty()) {
+        Date result = null;
+        if (datePattern != null && !datePattern.isEmpty()) {
             result = GenericTypeValidator.formatDate(value, datePattern, false);
         } else if (datePatternStrict != null && !datePatternStrict.isEmpty()) {
             result = GenericTypeValidator.formatDate(value, datePatternStrict, true);
         }
 
-      return result;
-   }
+        return result;
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>date</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>date</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Date validateDate(final Object bean, final Field field, final Locale locale) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatDate(value, locale);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>double</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>double</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Double validateDouble(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatDouble(value);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>double</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>double</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Double validateDouble(final Object bean, final Field field, final Locale locale) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatDouble(value, locale);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>float</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>float</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Float validateFloat(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatFloat(value);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>float</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>float</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Float validateFloat(final Object bean, final Field field, final Locale locale) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatFloat(value, locale);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>int</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>int</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Integer validateInt(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatInt(value);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>int</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>int</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Integer validateInt(final Object bean, final Field field, final Locale locale) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatInt(value, locale);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>long</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>long</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Long validateLong(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatLong(value);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>long</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>long</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Long validateLong(final Object bean, final Field field, final Locale locale) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatLong(value, locale);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>short</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>short</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Short validateShort(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatShort(value);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>short</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>short</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static Short validateShort(final Object bean, final Field field, final Locale locale) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatShort(value, locale);
+    }
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/GenericTypeValidatorTest.java b/src/test/java/org/apache/commons/validator/GenericTypeValidatorTest.java
index b3e7774..054dd01 100644
--- a/src/test/java/org/apache/commons/validator/GenericTypeValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/GenericTypeValidatorTest.java
@@ -16,11 +16,18 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.IOException;
 import java.util.Date;
 import java.util.Locale;
 import java.util.Map;
 
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
 /**
@@ -28,159 +35,157 @@
  */
 public class GenericTypeValidatorTest extends AbstractCommonTest {
 
-   /**
-    * The key used to retrieve the set of validation
-    * rules from the xml file.
-    */
-   protected static String FORM_KEY = "typeForm";
+    /**
+     * The key used to retrieve the set of validation rules from the xml file.
+     */
+    protected static String FORM_KEY = "typeForm";
 
-   /**
-    * The key used to retrieve the validator action.
-    */
-   protected static String ACTION = "byte";
+    /**
+     * The key used to retrieve the validator action.
+     */
+    protected static String ACTION = "byte";
 
-   public GenericTypeValidatorTest(final String name) {
-       super(name);
-   }
+    /**
+     * Tests the locale.
+     */
+    private Map<String, ?> localeTest(final TypeBean info, final Locale locale) throws ValidatorException {
 
-   /**
-    * Load <code>ValidatorResources</code> from
-    * validator-type.xml.
-    */
-   @Override
-protected void setUp() throws IOException, SAXException {
-      // Load resources
-      loadResources("GenericTypeValidatorTest-config.xml");
-   }
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, "typeLocaleForm");
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, info);
+        validator.setParameter("java.util.Locale", locale);
 
-   @Override
-protected void tearDown() {
-   }
+        // Get results of the validation.
+        // throws ValidatorException,
+        // but we aren't catching for testing
+        // since no validation methods we use
+        // throw this
+        final ValidatorResults results = validator.validate();
 
-   /**
-    * Tests the byte validation.
-    */
-   public void testType() throws ValidatorException {
-      // Create bean to run test on.
-      final TypeBean info = new TypeBean();
-      info.setByte("12");
-      info.setShort("129");
-      info.setInteger("-144");
-      info.setLong("88000");
-      info.setFloat("12.1555f");
-      info.setDouble("129.1551511111d");
+        assertNotNull(results, "Results are null.");
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, info);
+        final Map<String, ?> hResultValues = results.getResultValueMap();
 
-      // Get results of the validation.
-      // throws ValidatorException,
-      // but we aren't catching for testing
-      // since no validation methods we use
-      // throw this
-      final ValidatorResults results = validator.validate();
+        assertTrue(hResultValues.get("byte") instanceof Byte, () -> "Expecting byte result to be an instance of Byte for locale: " + locale);
+        assertTrue(hResultValues.get("short") instanceof Short, () -> "Expecting short result to be an instance of Short for locale: " + locale);
+        assertTrue(hResultValues.get("integer") instanceof Integer, () -> "Expecting integer result to be an instance of Integer for locale: " + locale);
+        assertTrue(hResultValues.get("long") instanceof Long, () -> "Expecting long result to be an instance of Long for locale: " + locale);
+        assertTrue(hResultValues.get("float") instanceof Float, () -> "Expecting float result to be an instance of Float for locale: " + locale);
+        assertTrue(hResultValues.get("double") instanceof Double, () -> "Expecting double result to be an instance of Double for locale: " + locale);
+        assertTrue(hResultValues.get("date") instanceof Date, () -> "Expecting date result to be an instance of Date for locale: " + locale);
 
-      assertNotNull("Results are null.", results);
+        for (final String key : hResultValues.keySet()) {
+            final Object value = hResultValues.get(key);
 
-      final Map<String, ?> hResultValues = results.getResultValueMap();
+            assertNotNull(value, () -> "value ValidatorResults.getResultValueMap() should not be null for locale: " + locale);
+        }
+        return hResultValues;
+    }
 
-      assertTrue("Expecting byte result to be an instance of Byte.", (hResultValues.get("byte") instanceof Byte));
-      assertTrue("Expecting short result to be an instance of Short.", (hResultValues.get("short") instanceof Short));
-      assertTrue("Expecting integer result to be an instance of Integer.", (hResultValues.get("integer") instanceof Integer));
-      assertTrue("Expecting long result to be an instance of Long.", (hResultValues.get("long") instanceof Long));
-      assertTrue("Expecting float result to be an instance of Float.", (hResultValues.get("float") instanceof Float));
-      assertTrue("Expecting double result to be an instance of Double.", (hResultValues.get("double") instanceof Double));
+    /**
+     * Load <code>ValidatorResources</code> from validator-type.xml.
+     */
+    @BeforeEach
+    protected void setUp() throws IOException, SAXException {
+        // Load resources
+        loadResources("GenericTypeValidatorTest-config.xml");
+    }
 
-      for (final String key : hResultValues.keySet()) {
-         final Object value = hResultValues.get(key);
+    @AfterEach
+    protected void tearDown() {
+    }
 
-         assertNotNull("value ValidatorResults.getResultValueMap() should not be null.", value);
-      }
+    /**
+     * Tests the fr locale.
+     */
+    @Test
+    public void testFRLocale() throws ValidatorException {
+        // Create bean to run test on.
+        final TypeBean info = new TypeBean();
+        info.setByte("12");
+        info.setShort("-129");
+        info.setInteger("1443");
+        info.setLong("88000");
+        info.setFloat("12,1555");
+        info.setDouble("129,1551511111");
+        info.setDate("21/12/2010");
+        final Map<String, ?> map = localeTest(info, Locale.FRENCH);
+        assertEquals(12, ((Float) map.get("float")).intValue(), "float value not correct");
+        assertEquals(129, ((Double) map.get("double")).intValue(), "double value not correct");
+    }
 
-      //ValidatorResult result = results.getValidatorResult("value");
+    /**
+     * Tests the byte validation.
+     */
+    @Test
+    public void testType() throws ValidatorException {
+        // Create bean to run test on.
+        final TypeBean info = new TypeBean();
+        info.setByte("12");
+        info.setShort("129");
+        info.setInteger("-144");
+        info.setLong("88000");
+        info.setFloat("12.1555f");
+        info.setDouble("129.1551511111d");
 
-      //assertNotNull(ACTION + " value ValidatorResult should not be null.", result);
-      //assertTrue(ACTION + " value ValidatorResult should contain the '" + ACTION +"' action.", result.containsAction(ACTION));
-      //assertTrue(ACTION + " value ValidatorResult for the '" + ACTION +"' action should have " + (passed ? "passed" : "failed") + ".", (passed ? result.isValid(ACTION) : !result.isValid(ACTION)));
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, info);
 
-   }
+        // Get results of the validation.
+        // throws ValidatorException,
+        // but we aren't catching for testing
+        // since no validation methods we use
+        // throw this
+        final ValidatorResults results = validator.validate();
 
-   /**
-    * Tests the us locale
-    */
-   public void testUSLocale() throws ValidatorException {
-      // Create bean to run test on.
-      final TypeBean info = new TypeBean();
-      info.setByte("12");
-      info.setShort("129");
-      info.setInteger("-144");
-      info.setLong("88000");
-      info.setFloat("12.1555");
-      info.setDouble("129.1551511111");
-      info.setDate("12/21/2010");
-      localeTest(info, Locale.US);
-   }
+        assertNotNull(results, "Results are null.");
 
-   /**
-    * Tests the fr locale.
-    */
-   public void testFRLocale() throws ValidatorException {
-      // Create bean to run test on.
-      final TypeBean info = new TypeBean();
-      info.setByte("12");
-      info.setShort("-129");
-      info.setInteger("1443");
-      info.setLong("88000");
-      info.setFloat("12,1555");
-      info.setDouble("129,1551511111");
-      info.setDate("21/12/2010");
-      final Map<String, ?> map = localeTest(info, Locale.FRENCH);
-      assertTrue("float value not correct", ((Float)map.get("float")).intValue() == 12);
-      assertTrue("double value not correct", ((Double)map.get("double")).intValue() == 129);
-  }
+        final Map<String, ?> hResultValues = results.getResultValueMap();
 
-  /**
-    * Tests the locale.
-    */
-   private Map<String, ?> localeTest(final TypeBean info, final Locale locale) throws ValidatorException {
+        assertTrue(hResultValues.get("byte") instanceof Byte, "Expecting byte result to be an instance of Byte.");
+        assertTrue(hResultValues.get("short") instanceof Short, "Expecting short result to be an instance of Short.");
+        assertTrue(hResultValues.get("integer") instanceof Integer, "Expecting integer result to be an instance of Integer.");
+        assertTrue(hResultValues.get("long") instanceof Long, "Expecting long result to be an instance of Long.");
+        assertTrue(hResultValues.get("float") instanceof Float, "Expecting float result to be an instance of Float.");
+        assertTrue(hResultValues.get("double") instanceof Double, "Expecting double result to be an instance of Double.");
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, "typeLocaleForm");
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, info);
-      validator.setParameter("java.util.Locale", locale);
+        for (final String key : hResultValues.keySet()) {
+            final Object value = hResultValues.get(key);
 
-      // Get results of the validation.
-      // throws ValidatorException,
-      // but we aren't catching for testing
-      // since no validation methods we use
-      // throw this
-      final ValidatorResults results = validator.validate();
+            assertNotNull(value, "value ValidatorResults.getResultValueMap() should not be null.");
+        }
 
-      assertNotNull("Results are null.", results);
+        // ValidatorResult result = results.getValidatorResult("value");
 
-      final Map<String, ?> hResultValues = results.getResultValueMap();
+        // assertNotNull(ACTION + " value ValidatorResult should not be null.", result);
+        // assertTrue(ACTION + " value ValidatorResult should contain the '" + ACTION +"' action.", result.containsAction(ACTION));
+        // assertTrue(ACTION + " value ValidatorResult for the '" + ACTION +"' action should have " + (passed ? "passed" : "failed") + ".", (passed ?
+        // result.isValid(ACTION) : !result.isValid(ACTION)));
 
-      assertTrue("Expecting byte result to be an instance of Byte for locale: "+locale, (hResultValues.get("byte") instanceof Byte));
-      assertTrue("Expecting short result to be an instance of Short for locale: "+locale, (hResultValues.get("short") instanceof Short));
-      assertTrue("Expecting integer result to be an instance of Integer for locale: "+locale, (hResultValues.get("integer") instanceof Integer));
-      assertTrue("Expecting long result to be an instance of Long for locale: "+locale, (hResultValues.get("long") instanceof Long));
-      assertTrue("Expecting float result to be an instance of Float for locale: "+locale, (hResultValues.get("float") instanceof Float));
-      assertTrue("Expecting double result to be an instance of Double for locale: "+locale, (hResultValues.get("double") instanceof Double));
-      assertTrue("Expecting date result to be an instance of Date for locale: "+locale, (hResultValues.get("date") instanceof Date));
+    }
 
-      for (final String key : hResultValues.keySet()) {
-         final Object value = hResultValues.get(key);
-
-         assertNotNull("value ValidatorResults.getResultValueMap() should not be null for locale: "+locale, value);
-      }
-      return hResultValues;
-   }
+    /**
+     * Tests the us locale
+     */
+    @Test
+    public void testUSLocale() throws ValidatorException {
+        // Create bean to run test on.
+        final TypeBean info = new TypeBean();
+        info.setByte("12");
+        info.setShort("129");
+        info.setInteger("-144");
+        info.setLong("88000");
+        info.setFloat("12.1555");
+        info.setDouble("129.1551511111");
+        info.setDate("12/21/2010");
+        localeTest(info, Locale.US);
+    }
 
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/GenericValidatorImpl.java b/src/test/java/org/apache/commons/validator/GenericValidatorImpl.java
index eeb8e2a..701622c 100644
--- a/src/test/java/org/apache/commons/validator/GenericValidatorImpl.java
+++ b/src/test/java/org/apache/commons/validator/GenericValidatorImpl.java
@@ -23,25 +23,121 @@
  */
 public class GenericValidatorImpl {
 
-    /**
-     * Throws a runtime exception if the value of the argument is "RUNTIME",
-     * an exception if the value of the argument is "CHECKED", and a
-     * ValidatorException otherwise.
-     *
-     * @throws RuntimeException with "RUNTIME-EXCEPTION as message"
-     * if value is "RUNTIME"
-     * @throws Exception with "CHECKED-EXCEPTION" as message
-     * if value is "CHECKED"
-     * @throws ValidatorException with "VALIDATOR-EXCEPTION" as message
-     * otherwise
-     */
-    public static boolean validateRaiseException(
-        final Object bean,
-        final Field field)
-        throws Exception {
+    public final static String FIELD_TEST_NULL = "NULL";
 
-        final String value =
-            ValidatorUtils.getValueAsString(bean, field.getProperty());
+    public final static String FIELD_TEST_NOTNULL = "NOTNULL";
+
+    public final static String FIELD_TEST_EQUAL = "EQUAL";
+
+    private static boolean isStringOrNull(final Object o) {
+        if (o == null) {
+            return true; // TODO this condition is not exercised by any tests currently
+        }
+        return o instanceof String;
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>byte</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>byte</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static boolean validateByte(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericValidator.isByte(value);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>double</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>double</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static boolean validateDouble(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericValidator.isDouble(value);
+    }
+
+    /**
+     * Checks if the field is an e-mail address.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field is an e-mail address {@code true} is returned. Otherwise {@code false}.
+     */
+    public static boolean validateEmail(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericValidator.isEmail(value);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>float</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>float</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static boolean validateFloat(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericValidator.isFloat(value);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>int</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>int</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static boolean validateInt(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericValidator.isInt(value);
+    }
+
+    /**
+     * Checks if the field can be successfully converted to a <code>long</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>long</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static boolean validateLong(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericValidator.isLong(value);
+    }
+
+    /**
+     * Checks if field is positive assuming it is an integer
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field Description of the field to be evaluated
+     * @return boolean If the integer field is greater than zero, returns true, otherwise returns false.
+     */
+    public static boolean validatePositive(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericTypeValidator.formatInt(value).intValue() > 0;
+    }
+
+    /**
+     * Throws a runtime exception if the value of the argument is "RUNTIME", an exception if the value of the argument is "CHECKED", and a ValidatorException
+     * otherwise.
+     *
+     * @throws RuntimeException   with "RUNTIME-EXCEPTION as message" if value is "RUNTIME"
+     * @throws Exception          with "CHECKED-EXCEPTION" as message if value is "CHECKED"
+     * @throws ValidatorException with "VALIDATOR-EXCEPTION" as message otherwise
+     */
+    public static boolean validateRaiseException(final Object bean, final Field field) throws Exception {
+
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
 
         if ("RUNTIME".equals(value)) {
             throw new RuntimeException("RUNTIME-EXCEPTION");
@@ -54,146 +150,18 @@
         throw new ValidatorException("VALIDATOR-EXCEPTION");
     }
 
-   /**
-    * Checks if the field is required.
-    *
-    * @return boolean If the field isn't <code>null</code> and
-    * has a length greater than zero, <code>true</code> is returned.
-    * Otherwise <code>false</code>.
-    */
-   public static boolean validateRequired(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+    /**
+     * Checks if the field is required.
+     *
+     * @return boolean If the field isn't {@code null} and has a length greater than zero, {@code true} is returned. Otherwise {@code false}.
+     */
+    public static boolean validateRequired(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
 
-      return !GenericValidator.isBlankOrNull(value);
-   }
+        return !GenericValidator.isBlankOrNull(value);
+    }
 
-   /**
-    * Checks if the field can be successfully converted to a <code>byte</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return    boolean        If the field can be successfully converted
-    *                           to a <code>byte</code> <code>true</code> is returned.
-    *                           Otherwise <code>false</code>.
-    */
-   public static boolean validateByte(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericValidator.isByte(value);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>short</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return    boolean        If the field can be successfully converted
-    *                           to a <code>short</code> <code>true</code> is returned.
-    *                           Otherwise <code>false</code>.
-    */
-   public static boolean validateShort(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericValidator.isShort(value);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>int</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return    boolean        If the field can be successfully converted
-    *                           to a <code>int</code> <code>true</code> is returned.
-    *                           Otherwise <code>false</code>.
-    */
-   public static boolean validateInt(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericValidator.isInt(value);
-   }
-
-   /**
-    * Checks if field is positive assuming it is an integer
-    *
-    * @param    bean       The value validation is being performed on.
-    * @param    field       Description of the field to be evaluated
-    * @return   boolean     If the integer field is greater than zero, returns
-    *                        true, otherwise returns false.
-    */
-   public static boolean validatePositive(final Object bean , final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericTypeValidator.formatInt(value).intValue() > 0;
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>long</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return    boolean        If the field can be successfully converted
-    *                           to a <code>long</code> <code>true</code> is returned.
-    *                           Otherwise <code>false</code>.
-    */
-   public static boolean validateLong(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericValidator.isLong(value);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>float</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return    boolean        If the field can be successfully converted
-    *                           to a <code>float</code> <code>true</code> is returned.
-    *                           Otherwise <code>false</code>.
-    */
-   public static boolean validateFloat(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericValidator.isFloat(value);
-   }
-
-   /**
-    * Checks if the field can be successfully converted to a <code>double</code>.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return    boolean        If the field can be successfully converted
-    *                           to a <code>double</code> <code>true</code> is returned.
-    *                           Otherwise <code>false</code>.
-    */
-   public static boolean validateDouble(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericValidator.isDouble(value);
-   }
-
-   /**
-    * Checks if the field is an e-mail address.
-    *
-    * @param bean The value validation is being performed on.
-    * @param field the field to use
-    * @return    boolean        If the field is an e-mail address
-    *                           <code>true</code> is returned.
-    *                           Otherwise <code>false</code>.
-    */
-   public static boolean validateEmail(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-
-      return GenericValidator.isEmail(value);
-   }
-
-  public final static String FIELD_TEST_NULL = "NULL";
-  public final static String FIELD_TEST_NOTNULL = "NOTNULL";
-  public final static String FIELD_TEST_EQUAL = "EQUAL";
-
-    public static boolean validateRequiredIf(
-        final Object bean,
-        final Field field,
-        final Validator validator) {
+    public static boolean validateRequiredIf(final Object bean, final Field field, final Validator validator) {
 
         final Object form = validator.getParameterValue(Validator.BEAN_PARAM);
         String value = null;
@@ -220,23 +188,23 @@
                 dependIndexed = "false";
             }
             boolean this_required = false;
-            if (field.isIndexed() && dependIndexed.equalsIgnoreCase("true")) {
+            if (field.isIndexed() && Boolean.parseBoolean(dependIndexed)) {
                 final String key = field.getKey();
-                if ((key.contains("[")) && (key.contains("]"))) {
+                if (key.contains("[") && key.contains("]")) {
                     final String ind = key.substring(0, key.indexOf(".") + 1);
                     dependProp = ind + dependProp;
                 }
             }
             final String dependVal = ValidatorUtils.getValueAsString(form, dependProp);
             if (dependTest.equals(FIELD_TEST_NULL)) {
-                if ((dependVal != null) && (!dependVal.isEmpty())) {
+                if (dependVal != null && !dependVal.isEmpty()) {
                     this_required = false;
                 } else {
                     this_required = true;
                 }
             }
             if (dependTest.equals(FIELD_TEST_NOTNULL)) {
-                if ((dependVal != null) && (!dependVal.isEmpty())) {
+                if (dependVal != null && !dependVal.isEmpty()) {
                     this_required = true;
                 } else {
                     this_required = false;
@@ -253,7 +221,7 @@
             i++;
         }
         if (required) {
-            if ((value != null) && (!value.isEmpty())) {
+            if (value != null && !value.isEmpty()) {
                 return true;
             }
             return false;
@@ -261,11 +229,17 @@
         return true;
     }
 
-  private static boolean isStringOrNull(final Object o) {
-    if (o == null) {
-        return true; // TODO this condition is not exercised by any tests currently
+    /**
+     * Checks if the field can be successfully converted to a <code>short</code>.
+     *
+     * @param bean  The value validation is being performed on.
+     * @param field the field to use
+     * @return boolean If the field can be successfully converted to a <code>short</code> {@code true} is returned. Otherwise {@code false}.
+     */
+    public static boolean validateShort(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+
+        return GenericValidator.isShort(value);
     }
-    return (o instanceof String);
-  }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/GenericValidatorTest.java b/src/test/java/org/apache/commons/validator/GenericValidatorTest.java
index 08f4555..15e70cf 100644
--- a/src/test/java/org/apache/commons/validator/GenericValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/GenericValidatorTest.java
@@ -16,60 +16,58 @@
  */
 package org.apache.commons.validator;
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
 
 /**
  * Test the GenericValidator class.
  */
-public class GenericValidatorTest extends TestCase {
+public class GenericValidatorTest {
 
-    /**
-     * Constructor for GenericValidatorTest.
-     */
-    public GenericValidatorTest(final String name) {
-        super(name);
-    }
-
-    public void testMinLength() {
-
-        // Use 0 for line end length
-        assertTrue("Min=5 End=0",  GenericValidator.minLength("12345\n\r", 5, 0));
-        assertFalse("Min=6 End=0", GenericValidator.minLength("12345\n\r", 6, 0));
-        assertFalse("Min=7 End=0", GenericValidator.minLength("12345\n\r", 7, 0));
-        assertFalse("Min=8 End=0", GenericValidator.minLength("12345\n\r", 8, 0));
-
-        // Use 1 for line end length
-        assertTrue("Min=5 End=1",  GenericValidator.minLength("12345\n\r", 5, 1));
-        assertTrue("Min=6 End=1",  GenericValidator.minLength("12345\n\r", 6, 1));
-        assertFalse("Min=7 End=1", GenericValidator.minLength("12345\n\r", 7, 1));
-        assertFalse("Min=8 End=1", GenericValidator.minLength("12345\n\r", 8, 1));
-
-        // Use 2 for line end length
-        assertTrue("Min=5 End=2",  GenericValidator.minLength("12345\n\r", 5, 2));
-        assertTrue("Min=6 End=2",  GenericValidator.minLength("12345\n\r", 6, 2));
-        assertTrue("Min=7 End=2",  GenericValidator.minLength("12345\n\r", 7, 2));
-        assertFalse("Min=8 End=2", GenericValidator.minLength("12345\n\r", 8, 2));
-    }
-
+    @Test
     public void testMaxLength() {
 
         // Use 0 for line end length
-        assertFalse("Max=4 End=0", GenericValidator.maxLength("12345\n\r", 4, 0));
-        assertTrue("Max=5 End=0",  GenericValidator.maxLength("12345\n\r", 5, 0));
-        assertTrue("Max=6 End=0",  GenericValidator.maxLength("12345\n\r", 6, 0));
-        assertTrue("Max=7 End=0",  GenericValidator.maxLength("12345\n\r", 7, 0));
+        assertFalse(GenericValidator.maxLength("12345\n\r", 4, 0), "Max=4 End=0");
+        assertTrue(GenericValidator.maxLength("12345\n\r", 5, 0), "Max=5 End=0");
+        assertTrue(GenericValidator.maxLength("12345\n\r", 6, 0), "Max=6 End=0");
+        assertTrue(GenericValidator.maxLength("12345\n\r", 7, 0), "Max=7 End=0");
 
         // Use 1 for line end length
-        assertFalse("Max=4 End=1", GenericValidator.maxLength("12345\n\r", 4, 1));
-        assertFalse("Max=5 End=1", GenericValidator.maxLength("12345\n\r", 5, 1));
-        assertTrue("Max=6 End=1",  GenericValidator.maxLength("12345\n\r", 6, 1));
-        assertTrue("Max=7 End=1",  GenericValidator.maxLength("12345\n\r", 7, 1));
+        assertFalse(GenericValidator.maxLength("12345\n\r", 4, 1), "Max=4 End=1");
+        assertFalse(GenericValidator.maxLength("12345\n\r", 5, 1), "Max=5 End=1");
+        assertTrue(GenericValidator.maxLength("12345\n\r", 6, 1), "Max=6 End=1");
+        assertTrue(GenericValidator.maxLength("12345\n\r", 7, 1), "Max=7 End=1");
 
         // Use 2 for line end length
-        assertFalse("Max=4 End=2", GenericValidator.maxLength("12345\n\r", 4, 2));
-        assertFalse("Max=5 End=2", GenericValidator.maxLength("12345\n\r", 5, 2));
-        assertFalse("Max=6 End=2", GenericValidator.maxLength("12345\n\r", 6, 2));
-        assertTrue("Max=7 End=2",  GenericValidator.maxLength("12345\n\r", 7, 2));
+        assertFalse(GenericValidator.maxLength("12345\n\r", 4, 2), "Max=4 End=2");
+        assertFalse(GenericValidator.maxLength("12345\n\r", 5, 2), "Max=5 End=2");
+        assertFalse(GenericValidator.maxLength("12345\n\r", 6, 2), "Max=6 End=2");
+        assertTrue(GenericValidator.maxLength("12345\n\r", 7, 2), "Max=7 End=2");
+    }
+
+    @Test
+    public void testMinLength() {
+
+        // Use 0 for line end length
+        assertTrue(GenericValidator.minLength("12345\n\r", 5, 0), "Min=5 End=0");
+        assertFalse(GenericValidator.minLength("12345\n\r", 6, 0), "Min=6 End=0");
+        assertFalse(GenericValidator.minLength("12345\n\r", 7, 0), "Min=7 End=0");
+        assertFalse(GenericValidator.minLength("12345\n\r", 8, 0), "Min=8 End=0");
+
+        // Use 1 for line end length
+        assertTrue(GenericValidator.minLength("12345\n\r", 5, 1), "Min=5 End=1");
+        assertTrue(GenericValidator.minLength("12345\n\r", 6, 1), "Min=6 End=1");
+        assertFalse(GenericValidator.minLength("12345\n\r", 7, 1), "Min=7 End=1");
+        assertFalse(GenericValidator.minLength("12345\n\r", 8, 1), "Min=8 End=1");
+
+        // Use 2 for line end length
+        assertTrue(GenericValidator.minLength("12345\n\r", 5, 2), "Min=5 End=2");
+        assertTrue(GenericValidator.minLength("12345\n\r", 6, 2), "Min=6 End=2");
+        assertTrue(GenericValidator.minLength("12345\n\r", 7, 2), "Min=7 End=2");
+        assertFalse(GenericValidator.minLength("12345\n\r", 8, 2), "Min=8 End=2");
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/ISBNValidatorTest.java b/src/test/java/org/apache/commons/validator/ISBNValidatorTest.java
index c38980a..cefd704 100644
--- a/src/test/java/org/apache/commons/validator/ISBNValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/ISBNValidatorTest.java
@@ -16,15 +16,18 @@
  */
 package org.apache.commons.validator;
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
 
 /**
- * ISBNValidator Test Case.
+ * Tests {@link ISBNValidator}.
  *
  * @deprecated to be removed when the org.apache.commons.validator.ISBNValidator class is removed
  */
 @Deprecated
-public class ISBNValidatorTest extends TestCase {
+public class ISBNValidatorTest {
 
     private static final String VALID_ISBN_RAW = "1930110995";
     private static final String VALID_ISBN_DASHES = "1-930110-99-5";
@@ -32,10 +35,7 @@
     private static final String VALID_ISBN_X = "0-201-63385-X";
     private static final String INVALID_ISBN = "068-556-98-45";
 
-    public ISBNValidatorTest(final String name) {
-        super(name);
-    }
-
+    @Test
     public void testIsValid() throws Exception {
         final ISBNValidator validator = new ISBNValidator();
         assertFalse(validator.isValid(null));
diff --git a/src/test/java/org/apache/commons/validator/IntegerTest.java b/src/test/java/org/apache/commons/validator/IntegerTest.java
index cc7f6a3..ca4c1a1 100644
--- a/src/test/java/org/apache/commons/validator/IntegerTest.java
+++ b/src/test/java/org/apache/commons/validator/IntegerTest.java
@@ -16,17 +16,14 @@
  */
 package org.apache.commons.validator;
 
-
-
+import org.junit.jupiter.api.Test;
 
 /**
  * Performs Validation Test for <code>int</code> validations.
  */
 public class IntegerTest extends AbstractNumberTest {
 
-
-    public IntegerTest(final String name) {
-        super(name);
+    public IntegerTest() {
         FORM_KEY = "intForm";
         ACTION = "int";
     }
@@ -34,6 +31,7 @@
     /**
      * Tests the int validation.
      */
+    @Test
     public void testInt() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -43,19 +41,33 @@
     }
 
     /**
-     * Tests the int validation.
+     * Tests the int validation failure.
      */
-    public void testIntMin() throws ValidatorException {
+    @Test
+    public void testIntBeyondMax() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
-        info.setValue(Integer.toString(Integer.MIN_VALUE));
+        info.setValue(Integer.MAX_VALUE + "1");
 
-        valueTest(info, true);
+        valueTest(info, false);
+    }
+
+    /**
+     * Tests the int validation failure.
+     */
+    @Test
+    public void testIntBeyondMin() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+        info.setValue(Integer.MIN_VALUE + "1");
+
+        valueTest(info, false);
     }
 
     /**
      * Tests the int validation.
      */
+    @Test
     public void testIntegerMax() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -67,6 +79,7 @@
     /**
      * Tests the int validation failure.
      */
+    @Test
     public void testIntFailure() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -75,25 +88,15 @@
     }
 
     /**
-     * Tests the int validation failure.
+     * Tests the int validation.
      */
-    public void testIntBeyondMin() throws ValidatorException {
+    @Test
+    public void testIntMin() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
-        info.setValue(Integer.MIN_VALUE + "1");
+        info.setValue(Integer.toString(Integer.MIN_VALUE));
 
-        valueTest(info, false);
-    }
-
-    /**
-     * Tests the int validation failure.
-     */
-    public void testIntBeyondMax() throws ValidatorException {
-        // Create bean to run test on.
-        final ValueBean info = new ValueBean();
-        info.setValue(Integer.MAX_VALUE + "1");
-
-        valueTest(info, false);
+        valueTest(info, true);
     }
 
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/LocaleTest.java b/src/test/java/org/apache/commons/validator/LocaleTest.java
index fa0d917..7fc5b0c 100644
--- a/src/test/java/org/apache/commons/validator/LocaleTest.java
+++ b/src/test/java/org/apache/commons/validator/LocaleTest.java
@@ -16,9 +16,15 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
 import java.io.IOException;
 import java.util.Locale;
 
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
 /**
@@ -31,44 +37,33 @@
      */
     protected static String FORM_KEY = "nameForm";
 
-    /** The key used to retrieve the validator action.  */
+    /** The key used to retrieve the validator action. */
     protected static String ACTION = "required";
 
     /**
-     * Constructor for the LocaleTest object
-     *
-     * @param name  param
-     */
-    public LocaleTest(final String name) {
-        super(name);
-    }
-
-    /**
      * Load <code>ValidatorResources</code> from validator-locale.xml.
      *
-     * @throws IOException   If something goes wrong
-     * @throws SAXException  If something goes wrong
+     * @throws IOException  If something goes wrong
+     * @throws SAXException If something goes wrong
      */
-    @Override
-    protected void setUp()
-        throws IOException, SAXException {
+    @BeforeEach
+    protected void setUp() throws IOException, SAXException {
         // Load resources
         loadResources("LocaleTest-config.xml");
     }
 
     /** The teardown method for JUnit */
-    @Override
+    @AfterEach
     protected void tearDown() {
     }
 
     /**
-     * See what happens when we try to validate with a Locale, Country and
-     * variant. Also check if the added locale validation field is getting used.
+     * See what happens when we try to validate with a Locale, Country and variant. Also check if the added locale validation field is getting used.
      *
-     * @throws ValidatorException  If something goes wrong
+     * @throws ValidatorException If something goes wrong
      */
-    public void testLocale1()
-        throws ValidatorException {
+    @Test
+    public void testLocale1() throws ValidatorException {
         // Create bean to run test on.
         final NameBean name = new NameBean();
         name.setFirstName("");
@@ -78,13 +73,12 @@
     }
 
     /**
-     * See what happens when we try to validate with a Locale, Country and
-     * variant
+     * See what happens when we try to validate with a Locale, Country and variant
      *
-     * @throws ValidatorException  If something goes wrong
+     * @throws ValidatorException If something goes wrong
      */
-    public void testLocale2()
-        throws ValidatorException {
+    @Test
+    public void testLocale2() throws ValidatorException {
         // Create bean to run test on.
         final NameBean name = new NameBean();
         name.setFirstName("");
@@ -94,13 +88,12 @@
     }
 
     /**
-     * See what happens when we try to validate with a Locale, Country and
-     * variant
+     * See what happens when we try to validate with a Locale, Country and variant
      *
-     * @throws ValidatorException  If something goes wrong
+     * @throws ValidatorException If something goes wrong
      */
-    public void testLocale3()
-        throws ValidatorException {
+    @Test
+    public void testLocale3() throws ValidatorException {
         // Create bean to run test on.
         final NameBean name = new NameBean();
         name.setFirstName("");
@@ -110,14 +103,13 @@
     }
 
     /**
-     * See if a locale of en_UK_TEST falls back to en_UK instead of default form
-     * set. Bug #16920 states that this isn't happening, even though it is
-     * passing this test. see #16920.
+     * See if a locale of en_UK_TEST falls back to en_UK instead of default form set. Bug #16920 states that this isn't happening, even though it is passing
+     * this test. see #16920.
      *
-     * @throws ValidatorException  If something goes wrong
+     * @throws ValidatorException If something goes wrong
      */
-    public void testLocale4()
-        throws ValidatorException {
+    @Test
+    public void testLocale4() throws ValidatorException {
         // Create bean to run test on.
         final NameBean name = new NameBean();
         name.setFirstName("");
@@ -129,10 +121,10 @@
     /**
      * See if a locale of language=en falls back to default form set.
      *
-     * @throws ValidatorException  If something goes wrong
+     * @throws ValidatorException If something goes wrong
      */
-    public void testLocale5()
-        throws ValidatorException {
+    @Test
+    public void testLocale5() throws ValidatorException {
         // Create bean to run test on.
         final NameBean name = new NameBean();
         name.setFirstName("");
@@ -144,15 +136,15 @@
     /**
      * Utlity class to run a test on a value.
      *
-     * @param name                    param
-     * @param loc                     param
-     * @param firstGood               param
-     * @param lastGood                param
-     * @param middleGood              param
-     * @throws ValidatorException  If something goes wrong
+     * @param name       param
+     * @param loc        param
+     * @param firstGood  param
+     * @param lastGood   param
+     * @param middleGood param
+     * @throws ValidatorException If something goes wrong
      */
     private void valueTest(final Object name, final Locale loc, final boolean firstGood, final boolean lastGood, final boolean middleGood)
-        throws ValidatorException {
+            throws ValidatorException {
 
         // Construct validator based on the loaded resources
         // and the form key
@@ -168,7 +160,7 @@
         // throw this
         final ValidatorResults results = validator.validate();
 
-        assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
         final ValidatorResult resultlast = results.getValidatorResult("lastName");
         final ValidatorResult resultfirst = results.getValidatorResult("firstName");
@@ -176,24 +168,20 @@
 
         if (firstGood) {
             assertNull(resultfirst);
-        }
-        else {
+        } else {
             assertNotNull(resultfirst);
         }
 
         if (middleGood) {
             assertNull(resultmiddle);
-        }
-        else {
+        } else {
             assertNotNull(resultmiddle);
         }
 
         if (lastGood) {
             assertNull(resultlast);
-        }
-        else {
+        } else {
             assertNotNull(resultlast);
         }
     }
 }
-
diff --git a/src/test/java/org/apache/commons/validator/LongTest.java b/src/test/java/org/apache/commons/validator/LongTest.java
index 0500e1e..e2d238e 100644
--- a/src/test/java/org/apache/commons/validator/LongTest.java
+++ b/src/test/java/org/apache/commons/validator/LongTest.java
@@ -16,14 +16,14 @@
  */
 package org.apache.commons.validator;
 
+import org.junit.jupiter.api.Test;
 
 /**
  * Performs Validation Test for <code>long</code> validations.
  */
 public class LongTest extends AbstractNumberTest {
 
-    public LongTest(final String name) {
-        super(name);
+    public LongTest() {
         FORM_KEY = "longForm";
         ACTION = "long";
     }
@@ -31,6 +31,7 @@
     /**
      * Tests the long validation.
      */
+    @Test
     public void testLong() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -40,33 +41,13 @@
     }
 
     /**
-     * Tests the long validation.
-     */
-    public void testLongMin() throws ValidatorException {
-        // Create bean to run test on.
-        final ValueBean info = new ValueBean();
-        info.setValue(Long.toString(Long.MIN_VALUE));
-
-        valueTest(info, true);
-    }
-
-    /**
-     * Tests the long validation.
-     */
-    public void testLongMax() throws ValidatorException {
-        // Create bean to run test on.
-        final ValueBean info = new ValueBean();
-        info.setValue(Long.toString(Long.MAX_VALUE));
-
-        valueTest(info, true);
-    }
-
-    /**
      * Tests the long validation failure.
      */
-    public void testLongFailure() throws ValidatorException {
+    @Test
+    public void testLongBeyondMax() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
+        info.setValue(Long.MAX_VALUE + "1");
 
         valueTest(info, false);
     }
@@ -74,6 +55,7 @@
     /**
      * Tests the long validation failure.
      */
+    @Test
     public void testLongBeyondMin() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
@@ -85,12 +67,36 @@
     /**
      * Tests the long validation failure.
      */
-    public void testLongBeyondMax() throws ValidatorException {
+    @Test
+    public void testLongFailure() throws ValidatorException {
         // Create bean to run test on.
         final ValueBean info = new ValueBean();
-        info.setValue(Long.MAX_VALUE + "1");
 
         valueTest(info, false);
     }
 
+    /**
+     * Tests the long validation.
+     */
+    @Test
+    public void testLongMax() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+        info.setValue(Long.toString(Long.MAX_VALUE));
+
+        valueTest(info, true);
+    }
+
+    /**
+     * Tests the long validation.
+     */
+    @Test
+    public void testLongMin() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+        info.setValue(Long.toString(Long.MIN_VALUE));
+
+        valueTest(info, true);
+    }
+
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/MultipleConfigFilesTest.java b/src/test/java/org/apache/commons/validator/MultipleConfigFilesTest.java
index a481670..c848c6e 100644
--- a/src/test/java/org/apache/commons/validator/MultipleConfigFilesTest.java
+++ b/src/test/java/org/apache/commons/validator/MultipleConfigFilesTest.java
@@ -16,27 +16,24 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.IOException;
 import java.io.InputStream;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
-import junit.framework.TestCase;
-
 /**
- * Tests that validator rules split between 2 different XML files get
- * merged properly.
+ * Tests that validator rules split between 2 different XML files get merged properly.
  */
-public class MultipleConfigFilesTest extends TestCase {
+public class MultipleConfigFilesTest {
 
     /**
-     * Resources used for validation tests.
-     */
-    private ValidatorResources resources;
-
-    /**
-     * The key used to retrieve the set of validation
-     * rules from the xml file.
+     * The key used to retrieve the set of validation rules from the xml file.
      */
     private static final String FORM_KEY = "nameForm";
 
@@ -46,24 +43,17 @@
     private static final String ACTION = "required";
 
     /**
-     * Constructor for MultipleConfigFilesTest.
-     * @param name
+     * Resources used for validation tests.
      */
-    public MultipleConfigFilesTest(final String name) {
-        super(name);
-    }
+    private ValidatorResources resources;
 
     /**
      * Load <code>ValidatorResources</code> from multiple xml files.
      */
-    @Override
+    @BeforeEach
     protected void setUp() throws IOException, SAXException {
-        final InputStream[] streams =
-            {
-            this.getClass().getResourceAsStream(
-                "MultipleConfigFilesTest-1-config.xml"),
-            this.getClass().getResourceAsStream(
-                "MultipleConfigFilesTest-2-config.xml")};
+        final InputStream[] streams = { this.getClass().getResourceAsStream("MultipleConfigFilesTest-1-config.xml"),
+                this.getClass().getResourceAsStream("MultipleConfigFilesTest-2-config.xml") };
 
         this.resources = new ValidatorResources(streams);
 
@@ -72,56 +62,10 @@
         }
     }
 
-   /**
-    * Check the forms and constants from different config files have
-    * been merged into the same FormSet.
-    */
-    public void testMergedConfig() {
-
-        // *********** Default Locale *******************
-
-        // Check the form from the first config file exists
-        final Form form1 = resources.getForm("", "", "", "testForm1");
-        assertNotNull("Form 'testForm1' not found", form1);
-
-        // Check the form from the second config file exists
-        final Form form2 = resources.getForm("", "", "", "testForm2");
-        assertNotNull("Form 'testForm2' not found", form2);
-
-        // Check the Constants  for the form from the first config file
-        final Field field1 = form1.getField("testProperty1");
-        assertEquals("testProperty1 - const 1", "testConstValue1", field1.getVarValue("var11"));
-        assertEquals("testProperty1 - const 2", "testConstValue2", field1.getVarValue("var12"));
-
-        // Check the Constants  for the form from the second config file
-        final Field field2 = form2.getField("testProperty2");
-        assertEquals("testProperty2 - const 1", "testConstValue1", field2.getVarValue("var21"));
-        assertEquals("testProperty2 - const 2", "testConstValue2", field2.getVarValue("var22"));
-
-        // *********** 'fr' locale *******************
-
-        // Check the form from the first config file exists
-        final Form form1_fr = resources.getForm("fr", "", "", "testForm1_fr");
-        assertNotNull("Form 'testForm1_fr' not found", form1_fr);
-
-        // Check the form from the second config file exists
-        final Form form2_fr = resources.getForm("fr", "", "", "testForm2_fr");
-        assertNotNull("Form 'testForm2_fr' not found", form2_fr);
-
-        // Check the Constants  for the form from the first config file
-        final Field field1_fr = form1_fr.getField("testProperty1_fr");
-        assertEquals("testProperty1_fr - const 1", "testConstValue1_fr", field1_fr.getVarValue("var11_fr"));
-        assertEquals("testProperty1_fr - const 2", "testConstValue2_fr", field1_fr.getVarValue("var12_fr"));
-
-        // Check the Constants  for the form from the second config file
-        final Field field2_fr = form2_fr.getField("testProperty2_fr");
-        assertEquals("testProperty2_fr - const 1", "testConstValue1_fr", field2_fr.getVarValue("var21_fr"));
-        assertEquals("testProperty2_fr - const 2", "testConstValue2_fr", field2_fr.getVarValue("var22_fr"));
-    }
-
     /**
-    * With nothing provided, we should fail both because both are required.
-    */
+     * With nothing provided, we should fail both because both are required.
+     */
+    @Test
     public void testBothBlank() throws ValidatorException {
         // Create bean to run test on.
         final NameBean name = new NameBean();
@@ -140,7 +84,7 @@
         // throw this
         final ValidatorResults results = validator.validate();
 
-        assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
         final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
         final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
@@ -156,10 +100,57 @@
     }
 
     /**
+     * Check the forms and constants from different config files have been merged into the same FormSet.
+     */
+    @Test
+    public void testMergedConfig() {
+
+        // *********** Default Locale *******************
+
+        // Check the form from the first config file exists
+        final Form form1 = resources.getForm("", "", "", "testForm1");
+        assertNotNull(form1, "Form 'testForm1' not found");
+
+        // Check the form from the second config file exists
+        final Form form2 = resources.getForm("", "", "", "testForm2");
+        assertNotNull(form2, "Form 'testForm2' not found");
+
+        // Check the Constants for the form from the first config file
+        final Field field1 = form1.getField("testProperty1");
+        assertEquals("testConstValue1", field1.getVarValue("var11"), "testProperty1 - const 1");
+        assertEquals("testConstValue2", field1.getVarValue("var12"), "testProperty1 - const 2");
+
+        // Check the Constants for the form from the second config file
+        final Field field2 = form2.getField("testProperty2");
+        assertEquals("testConstValue1", field2.getVarValue("var21"), "testProperty2 - const 1");
+        assertEquals("testConstValue2", field2.getVarValue("var22"), "testProperty2 - const 2");
+
+        // *********** 'fr' locale *******************
+
+        // Check the form from the first config file exists
+        final Form form1_fr = resources.getForm("fr", "", "", "testForm1_fr");
+        assertNotNull(form1_fr, "Form 'testForm1_fr' not found");
+
+        // Check the form from the second config file exists
+        final Form form2_fr = resources.getForm("fr", "", "", "testForm2_fr");
+        assertNotNull(form2_fr, "Form 'testForm2_fr' not found");
+
+        // Check the Constants for the form from the first config file
+        final Field field1_fr = form1_fr.getField("testProperty1_fr");
+        assertEquals("testConstValue1_fr", field1_fr.getVarValue("var11_fr"), "testProperty1_fr - const 1");
+        assertEquals("testConstValue2_fr", field1_fr.getVarValue("var12_fr"), "testProperty1_fr - const 2");
+
+        // Check the Constants for the form from the second config file
+        final Field field2_fr = form2_fr.getField("testProperty2_fr");
+        assertEquals("testConstValue1_fr", field2_fr.getVarValue("var21_fr"), "testProperty2_fr - const 1");
+        assertEquals("testConstValue2_fr", field2_fr.getVarValue("var22_fr"), "testProperty2_fr - const 2");
+    }
+
+    /**
      * If the first name fails required, and the second test fails int, we should get two errors.
-    */
-    public void testRequiredFirstNameBlankLastNameShort()
-        throws ValidatorException {
+     */
+    @Test
+    public void testRequiredFirstNameBlankLastNameShort() throws ValidatorException {
         // Create bean to run test on.
         final NameBean name = new NameBean();
         name.setFirstName("");
@@ -175,7 +166,7 @@
         // Get results of the validation.
         final ValidatorResults results = validator.validate();
 
-        assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
         final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
         final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
@@ -190,41 +181,9 @@
     }
 
     /**
-     * If the first name is there, and the last name fails int, we should get one error.
-    */
-    public void testRequiredLastNameShort() throws ValidatorException {
-        // Create bean to run test on.
-        final NameBean name = new NameBean();
-        name.setFirstName("Test");
-        name.setLastName("Test");
-
-        // Construct validator based on the loaded resources
-        // and the form key
-        final Validator validator = new Validator(resources, FORM_KEY);
-        // add the name bean to the validator as a resource
-        // for the validations to be performed on.
-        validator.setParameter(Validator.BEAN_PARAM, name);
-
-        // Get results of the validation.
-        final ValidatorResults results = validator.validate();
-
-        assertNotNull("Results are null.", results);
-
-        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
-
-        assertNotNull(firstNameResult);
-        assertTrue(firstNameResult.containsAction(ACTION));
-        assertTrue(firstNameResult.isValid(ACTION));
-
-        assertNotNull(lastNameResult);
-        assertTrue(lastNameResult.containsAction("int"));
-        assertTrue(!lastNameResult.isValid("int"));
-    }
-
-    /**
      * If first name is ok and last name is ok and is an int, no errors.
-    */
+     */
+    @Test
     public void testRequiredLastNameLong() throws ValidatorException {
         // Create bean to run test on.
         final NameBean name = new NameBean();
@@ -241,7 +200,7 @@
         // Get results of the validation.
         final ValidatorResults results = validator.validate();
 
-        assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
         final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
         final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
@@ -255,4 +214,38 @@
         assertTrue(lastNameResult.isValid("int"));
     }
 
+    /**
+     * If the first name is there, and the last name fails int, we should get one error.
+     */
+    @Test
+    public void testRequiredLastNameShort() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("Test");
+        name.setLastName("Test");
+
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
+
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
+
+        assertNotNull(results, "Results are null.");
+
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+
+        assertNotNull(firstNameResult);
+        assertTrue(firstNameResult.containsAction(ACTION));
+        assertTrue(firstNameResult.isValid(ACTION));
+
+        assertNotNull(lastNameResult);
+        assertTrue(lastNameResult.containsAction("int"));
+        assertTrue(!lastNameResult.isValid("int"));
+    }
+
 }
diff --git a/src/test/java/org/apache/commons/validator/MultipleTest.java b/src/test/java/org/apache/commons/validator/MultipleTest.java
index d605faf..a12a20f 100644
--- a/src/test/java/org/apache/commons/validator/MultipleTest.java
+++ b/src/test/java/org/apache/commons/validator/MultipleTest.java
@@ -16,8 +16,14 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.IOException;
 
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
 /**
@@ -25,314 +31,309 @@
  */
 public class MultipleTest extends AbstractCommonTest {
 
-   /**
-    * The key used to retrieve the set of validation
-    * rules from the xml file.
-    */
-   protected static String FORM_KEY = "nameForm";
+    /**
+     * The key used to retrieve the set of validation rules from the xml file.
+     */
+    protected static String FORM_KEY = "nameForm";
 
-   /**
-    * The key used to retrieve the validator action.
-    */
-   protected static String ACTION = "required";
+    /**
+     * The key used to retrieve the validator action.
+     */
+    protected static String ACTION = "required";
 
+    /**
+     * Load <code>ValidatorResources</code> from validator-multipletest.xml.
+     */
+    @BeforeEach
+    protected void setUp() throws IOException, SAXException {
+        // Load resources
+        loadResources("MultipleTests-config.xml");
+    }
 
+    @AfterEach
+    protected void tearDown() {
+    }
 
-   public MultipleTest(final String name) {
-       super(name);
-   }
+    /**
+     * With nothing provided, we should fail both because both are required.
+     */
+    @Test
+    public void testBothBlank() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
 
-   /**
-    * Load <code>ValidatorResources</code> from
-    * validator-multipletest.xml.
-    */
-   @Override
-protected void setUp() throws IOException, SAXException {
-      // Load resources
-      loadResources("MultipleTests-config.xml");
-   }
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-   @Override
-protected void tearDown() {
-   }
+        // Get results of the validation.
+        // throws ValidatorException,
+        // but we aren't catching for testing
+        // since no validation methods we use
+        // throw this
+        final ValidatorResults results = validator.validate();
 
-   /**
-    * With nothing provided, we should fail both because both are required.
-    */
-   public void testBothBlank() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
+        assertNotNull(results, "Results are null.");
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      // Get results of the validation.
-      // throws ValidatorException,
-      // but we aren't catching for testing
-      // since no validation methods we use
-      // throw this
-      final ValidatorResults results = validator.validate();
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have failed.");
 
-      assertNotNull("Results are null.", results);
+        assertNotNull(lastNameResult, "Last Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), () -> "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!lastNameResult.isValid(ACTION), () -> "Last Name ValidatorResult for the '" + ACTION + "' action should have failed.");
+        assertTrue(!lastNameResult.containsAction("int"), "Last Name ValidatorResults should not contain the 'int' action.");
+    }
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+    /**
+     * If middle name is not there, then the required dependent test should fail. No other tests should run
+     *
+     * @throws ValidatorException
+     */
+    @Test
+    public void testFailingFirstDependentValidator() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have failed.", !firstNameResult.isValid(ACTION));
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      assertNotNull("Last Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have failed.", !lastNameResult.isValid(ACTION));
-      assertTrue("Last Name ValidatorResults should not contain the 'int' action.", !lastNameResult.containsAction("int"));
-   }
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-   /**
-    * If the first name fails required, and the second test fails int, we should get two errors.
-    */
-   public void testRequiredFirstNameBlankLastNameShort() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setFirstName("");
-      name.setLastName("Test");
+        assertNotNull(results, "Results are null.");
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        final ValidatorResult middleNameResult = results.getValidatorResult("middleName");
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        assertNotNull(middleNameResult, "Middle Name ValidatorResult should not be null.");
 
-      assertNotNull("Results are null.", results);
+        assertTrue(middleNameResult.containsAction("required"), "Middle Name ValidatorResult should contain the 'required' action.");
+        assertTrue(!middleNameResult.isValid("required"), "Middle Name ValidatorResult for the 'required' action should have failed");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertTrue(!middleNameResult.containsAction("int"), "Middle Name ValidatorResult should not contain the 'int' action.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have failed.", !firstNameResult.isValid(ACTION));
+        assertTrue(!middleNameResult.containsAction("positive"), "Middle Name ValidatorResult should not contain the 'positive' action.");
+    }
 
-      assertNotNull("Last Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the 'int' action.", lastNameResult.containsAction("int"));
-      assertTrue("Last Name ValidatorResult for the 'int' action should have failed.", !lastNameResult.isValid("int"));
-   }
+    /**
+     * If middle name is there but not int, then the required dependent test should pass, but the int dependent test should fail. No other tests should run.
+     *
+     * @throws ValidatorException
+     */
+    @Test
+    public void testFailingNextDependentValidator() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setMiddleName("TEST");
 
-   /**
-    * If the first name is there, and the last name fails int, we should get one error.
-    */
-   public void testRequiredLastNameShort() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setFirstName("Test");
-      name.setLastName("Test");
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        assertNotNull(results, "Results are null.");
 
-      assertNotNull("Results are null.", results);
+        final ValidatorResult middleNameResult = results.getValidatorResult("middleName");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(middleNameResult, "Middle Name ValidatorResult should not be null.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have passed.", firstNameResult.isValid(ACTION));
+        assertTrue(middleNameResult.containsAction("required"), "Middle Name ValidatorResult should contain the 'required' action.");
+        assertTrue(middleNameResult.isValid("required"), "Middle Name ValidatorResult for the 'required' action should have passed");
 
-      assertNotNull("Last Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the 'int' action.", lastNameResult.containsAction("int"));
-      assertTrue("Last Name ValidatorResult for the 'int' action should have failed.", !lastNameResult.isValid("int"));
-   }
+        assertTrue(middleNameResult.containsAction("int"), "Middle Name ValidatorResult should contain the 'int' action.");
+        assertTrue(!middleNameResult.isValid("int"), "Middle Name ValidatorResult for the 'int' action should have failed");
 
-   /**
-    * If first name is ok and last name is ok and is an int, no errors.
-    */
-   public void testRequiredLastNameLong() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setFirstName("Joe");
-      name.setLastName("12345678");
+        assertTrue(!middleNameResult.containsAction("positive"), "Middle Name ValidatorResult should not contain the 'positive' action.");
+    }
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+    /**
+     * If middle name is there and a negative int, then the required and int dependent tests should pass, but the positive test should fail.
+     *
+     * @throws ValidatorException
+     */
+    @Test
+    public void testPassingDependentsFailingMain() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setMiddleName("-2534");
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      assertNotNull("Results are null.", results);
-
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
-
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have passed.", firstNameResult.isValid(ACTION));
-
-      assertNotNull("Last Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the 'int' action.", lastNameResult.containsAction("int"));
-      assertTrue("Last Name ValidatorResult for the 'int' action should have passed.", lastNameResult.isValid("int"));
-   }
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-   /**
-    * If middle name is not there, then the required dependent test should fail.
-    * No other tests should run
-    *
-    * @throws ValidatorException
-    */
-   public void testFailingFirstDependentValidator() throws ValidatorException {
-       // Create bean to run test on.
-       final NameBean name = new NameBean();
+        assertNotNull(results, "Results are null.");
 
-       // Construct validator based on the loaded resources
-       // and the form key
-       final Validator validator = new Validator(resources, FORM_KEY);
-       // add the name bean to the validator as a resource
-       // for the validations to be performed on.
-       validator.setParameter(Validator.BEAN_PARAM, name);
+        final ValidatorResult middleNameResult = results.getValidatorResult("middleName");
 
-       // Get results of the validation.
-       final ValidatorResults results = validator.validate();
+        assertNotNull(middleNameResult, "Middle Name ValidatorResult should not be null.");
 
-       assertNotNull("Results are null.", results);
+        assertTrue(middleNameResult.containsAction("required"), "Middle Name ValidatorResult should contain the 'required' action.");
+        assertTrue(middleNameResult.isValid("required"), "Middle Name ValidatorResult for the 'required' action should have passed");
 
-       final ValidatorResult middleNameResult = results.getValidatorResult("middleName");
+        assertTrue(middleNameResult.containsAction("int"), "Middle Name ValidatorResult should contain the 'int' action.");
+        assertTrue(middleNameResult.isValid("int"), "Middle Name ValidatorResult for the 'int' action should have passed");
 
-       assertNotNull("Middle Name ValidatorResult should not be null.", middleNameResult);
+        assertTrue(middleNameResult.containsAction("positive"), "Middle Name ValidatorResult should contain the 'positive' action.");
+        assertTrue(!middleNameResult.isValid("positive"), "Middle Name ValidatorResult for the 'positive' action should have failed");
+    }
 
-       assertTrue("Middle Name ValidatorResult should contain the 'required' action.", middleNameResult.containsAction("required"));
-       assertTrue("Middle Name ValidatorResult for the 'required' action should have failed", !middleNameResult.isValid("required"));
+    /**
+     * If middle name is there and a positve int, then the required and int dependent tests should pass, and the positive test should pass.
+     *
+     * @throws ValidatorException
+     */
+    @Test
+    public void testPassingDependentsPassingMain() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setMiddleName("2534");
 
-       assertTrue("Middle Name ValidatorResult should not contain the 'int' action.", !middleNameResult.containsAction("int"));
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-       assertTrue("Middle Name ValidatorResult should not contain the 'positive' action.", !middleNameResult.containsAction("positive"));
-   }
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-   /**
-    * If middle name is there but not int, then the required dependent test
-    * should pass, but the int dependent test should fail. No other tests should
-    * run.
-    *
-    * @throws ValidatorException
-    */
-   public void testFailingNextDependentValidator() throws ValidatorException {
-       // Create bean to run test on.
-       final NameBean name = new NameBean();
-       name.setMiddleName("TEST");
+        assertNotNull(results, "Results are null.");
 
-       // Construct validator based on the loaded resources
-       // and the form key
-       final Validator validator = new Validator(resources, FORM_KEY);
-       // add the name bean to the validator as a resource
-       // for the validations to be performed on.
-       validator.setParameter(Validator.BEAN_PARAM, name);
+        final ValidatorResult middleNameResult = results.getValidatorResult("middleName");
 
-       // Get results of the validation.
-       final ValidatorResults results = validator.validate();
+        assertNotNull(middleNameResult, "Middle Name ValidatorResult should not be null.");
 
-       assertNotNull("Results are null.", results);
+        assertTrue(middleNameResult.containsAction("required"), "Middle Name ValidatorResult should contain the 'required' action.");
+        assertTrue(middleNameResult.isValid("required"), "Middle Name ValidatorResult for the 'required' action should have passed");
 
-       final ValidatorResult middleNameResult = results.getValidatorResult("middleName");
+        assertTrue(middleNameResult.containsAction("int"), "Middle Name ValidatorResult should contain the 'int' action.");
+        assertTrue(middleNameResult.isValid("int"), "Middle Name ValidatorResult for the 'int' action should have passed");
 
-       assertNotNull("Middle Name ValidatorResult should not be null.", middleNameResult);
+        assertTrue(middleNameResult.containsAction("positive"), "Middle Name ValidatorResult should contain the 'positive' action.");
+        assertTrue(middleNameResult.isValid("positive"), "Middle Name ValidatorResult for the 'positive' action should have passed");
+    }
 
-       assertTrue("Middle Name ValidatorResult should contain the 'required' action.", middleNameResult.containsAction("required"));
-       assertTrue("Middle Name ValidatorResult for the 'required' action should have passed", middleNameResult.isValid("required"));
+    /**
+     * If the first name fails required, and the second test fails int, we should get two errors.
+     */
+    @Test
+    public void testRequiredFirstNameBlankLastNameShort() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("");
+        name.setLastName("Test");
 
-       assertTrue("Middle Name ValidatorResult should contain the 'int' action.", middleNameResult.containsAction("int"));
-       assertTrue("Middle Name ValidatorResult for the 'int' action should have failed", !middleNameResult.isValid("int"));
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-       assertTrue("Middle Name ValidatorResult should not contain the 'positive' action.", !middleNameResult.containsAction("positive"));
-   }
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-   /**
-    * If middle name is there and a negative int, then the required and int
-    * dependent tests should pass, but the positive test should fail.
-    *
-    * @throws ValidatorException
-    */
-   public void testPassingDependentsFailingMain() throws ValidatorException {
-       // Create bean to run test on.
-       final NameBean name = new NameBean();
-       name.setMiddleName("-2534");
+        assertNotNull(results, "Results are null.");
 
-       // Construct validator based on the loaded resources
-       // and the form key
-       final Validator validator = new Validator(resources, FORM_KEY);
-       // add the name bean to the validator as a resource
-       // for the validations to be performed on.
-       validator.setParameter(Validator.BEAN_PARAM, name);
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-       // Get results of the validation.
-       final ValidatorResults results = validator.validate();
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have failed.");
 
-       assertNotNull("Results are null.", results);
+        assertNotNull(lastNameResult, "Last Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction("int"), "Last Name ValidatorResult should contain the 'int' action.");
+        assertTrue(!lastNameResult.isValid("int"), "Last Name ValidatorResult for the 'int' action should have failed.");
+    }
 
-       final ValidatorResult middleNameResult = results.getValidatorResult("middleName");
+    /**
+     * If first name is ok and last name is ok and is an int, no errors.
+     */
+    @Test
+    public void testRequiredLastNameLong() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("Joe");
+        name.setLastName("12345678");
 
-       assertNotNull("Middle Name ValidatorResult should not be null.", middleNameResult);
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-       assertTrue("Middle Name ValidatorResult should contain the 'required' action.", middleNameResult.containsAction("required"));
-       assertTrue("Middle Name ValidatorResult for the 'required' action should have passed", middleNameResult.isValid("required"));
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-       assertTrue("Middle Name ValidatorResult should contain the 'int' action.", middleNameResult.containsAction("int"));
-       assertTrue("Middle Name ValidatorResult for the 'int' action should have passed", middleNameResult.isValid("int"));
+        assertNotNull(results, "Results are null.");
 
-       assertTrue("Middle Name ValidatorResult should contain the 'positive' action.", middleNameResult.containsAction("positive"));
-       assertTrue("Middle Name ValidatorResult for the 'positive' action should have failed", !middleNameResult.isValid("positive"));
-   }
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-   /**
-    * If middle name is there and a positve int, then the required and int
-    * dependent tests should pass, and the positive test should pass.
-    *
-    * @throws ValidatorException
-    */
-   public void testPassingDependentsPassingMain() throws ValidatorException {
-       // Create bean to run test on.
-       final NameBean name = new NameBean();
-       name.setMiddleName("2534");
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-       // Construct validator based on the loaded resources
-       // and the form key
-       final Validator validator = new Validator(resources, FORM_KEY);
-       // add the name bean to the validator as a resource
-       // for the validations to be performed on.
-       validator.setParameter(Validator.BEAN_PARAM, name);
+        assertNotNull(lastNameResult, "Last Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction("int"), "Last Name ValidatorResult should contain the 'int' action.");
+        assertTrue(lastNameResult.isValid("int"), "Last Name ValidatorResult for the 'int' action should have passed.");
+    }
 
-       // Get results of the validation.
-       final ValidatorResults results = validator.validate();
+    /**
+     * If the first name is there, and the last name fails int, we should get one error.
+     */
+    @Test
+    public void testRequiredLastNameShort() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("Test");
+        name.setLastName("Test");
 
-       assertNotNull("Results are null.", results);
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-       final ValidatorResult middleNameResult = results.getValidatorResult("middleName");
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-       assertNotNull("Middle Name ValidatorResult should not be null.", middleNameResult);
+        assertNotNull(results, "Results are null.");
 
-       assertTrue("Middle Name ValidatorResult should contain the 'required' action.", middleNameResult.containsAction("required"));
-       assertTrue("Middle Name ValidatorResult for the 'required' action should have passed", middleNameResult.isValid("required"));
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-       assertTrue("Middle Name ValidatorResult should contain the 'int' action.", middleNameResult.containsAction("int"));
-       assertTrue("Middle Name ValidatorResult for the 'int' action should have passed", middleNameResult.isValid("int"));
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-       assertTrue("Middle Name ValidatorResult should contain the 'positive' action.", middleNameResult.containsAction("positive"));
-       assertTrue("Middle Name ValidatorResult for the 'positive' action should have passed", middleNameResult.isValid("positive"));
-   }
+        assertNotNull(lastNameResult, "Last Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction("int"), "Last Name ValidatorResult should contain the 'int' action.");
+        assertTrue(!lastNameResult.isValid("int"), "Last Name ValidatorResult for the 'int' action should have failed.");
+    }
 }
diff --git a/src/test/java/org/apache/commons/validator/NameBean.java b/src/test/java/org/apache/commons/validator/NameBean.java
index c2ac1dd..abe983e 100644
--- a/src/test/java/org/apache/commons/validator/NameBean.java
+++ b/src/test/java/org/apache/commons/validator/NameBean.java
@@ -31,24 +31,24 @@
         return firstName;
     }
 
-    public void setFirstName(final String firstName) {
-        this.firstName = firstName;
+    public String getLastName() {
+        return lastName;
     }
 
     public String getMiddleName() {
         return middleName;
     }
 
-    public void setMiddleName(final String middleName) {
-        this.middleName = middleName;
-    }
-
-    public String getLastName() {
-        return lastName;
+    public void setFirstName(final String firstName) {
+        this.firstName = firstName;
     }
 
     public void setLastName(final String lastName) {
         this.lastName = lastName;
     }
 
+    public void setMiddleName(final String middleName) {
+        this.middleName = middleName;
+    }
+
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/ParameterTest.java b/src/test/java/org/apache/commons/validator/ParameterTest.java
index e8a5dca..f58913a 100644
--- a/src/test/java/org/apache/commons/validator/ParameterTest.java
+++ b/src/test/java/org/apache/commons/validator/ParameterTest.java
@@ -16,9 +16,16 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.io.IOException;
 import java.util.Locale;
 
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
 /**
@@ -34,18 +41,27 @@
 
     private String lastName;
 
-    /**
-     * Constructor.
-     */
-    public ParameterTest(final String name) {
-        super(name);
+    private void assertParameterValue(final Validator validator, final String name, final Class<?> type) {
+        final Object value = validator.getParameterValue(name);
+        assertNotNull(value, () -> "Expected '" + type.getName() + "' but was null");
+        assertTrue(type.isInstance(value), () -> "Expected '" + type.getName() + "' but was '" + value.getClass().getName() + "'");
     }
 
     /**
-     * Load <code>ValidatorResources</code> from
-     * ValidatorResultsTest-config.xml.
+     * Create a NameBean.
      */
-    @Override
+    private NameBean createNameBean() {
+        final NameBean name = new NameBean();
+        name.setFirstName(firstName);
+        name.setMiddleName(middleName);
+        name.setLastName(lastName);
+        return name;
+    }
+
+    /**
+     * Load <code>ValidatorResources</code> from ValidatorResultsTest-config.xml.
+     */
+    @BeforeEach
     protected void setUp() throws IOException, SAXException {
         // Load resources
         loadResources("ParameterTest-config.xml");
@@ -57,13 +73,14 @@
 
     }
 
-    @Override
+    @AfterEach
     protected void tearDown() {
     }
 
     /**
      * Test all validations ran and passed.
      */
+    @Test
     public void testAllValid() {
 
         // Create bean to run test on.
@@ -79,37 +96,15 @@
         // Get results of the validation.
         try {
             validator.validate();
-        } catch(final Exception e) {
+        } catch (final Exception e) {
             fail("Validator.validate() threw " + e);
         }
         assertParameterValue(validator, Validator.BEAN_PARAM, Object.class);
         assertParameterValue(validator, Validator.FIELD_PARAM, Field.class);
         assertParameterValue(validator, Validator.FORM_PARAM, Form.class);
         assertParameterValue(validator, Validator.LOCALE_PARAM, Locale.class);
-        assertParameterValue(validator, Validator.VALIDATOR_ACTION_PARAM,
-                ValidatorAction.class);
-        assertParameterValue(validator, Validator.VALIDATOR_PARAM,
-                Validator.class);
-        assertParameterValue(validator, Validator.VALIDATOR_RESULTS_PARAM,
-                ValidatorResults.class);
-    }
-
-    private void assertParameterValue(final Validator validator, final String name,
-            final Class<?> type) {
-        final Object value = validator.getParameterValue(name);
-        assertNotNull("Expected '" + type.getName() + "' but was null", value);
-        assertTrue("Expected '" + type.getName() + "' but was '" + value.getClass().getName() + "'",
-                   type.isInstance(value));
-    }
-
-    /**
-     * Create a NameBean.
-     */
-    private NameBean createNameBean() {
-        final NameBean name = new NameBean();
-        name.setFirstName(firstName);
-        name.setMiddleName(middleName);
-        name.setLastName(lastName);
-        return name;
+        assertParameterValue(validator, Validator.VALIDATOR_ACTION_PARAM, ValidatorAction.class);
+        assertParameterValue(validator, Validator.VALIDATOR_PARAM, Validator.class);
+        assertParameterValue(validator, Validator.VALIDATOR_RESULTS_PARAM, ValidatorResults.class);
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/ParameterValidatorImpl.java b/src/test/java/org/apache/commons/validator/ParameterValidatorImpl.java
index e46873f..f4808b9 100644
--- a/src/test/java/org/apache/commons/validator/ParameterValidatorImpl.java
+++ b/src/test/java/org/apache/commons/validator/ParameterValidatorImpl.java
@@ -23,17 +23,11 @@
 

     /**

      * ValidatorParameter is valid.

-     *

      */

-    public static boolean validateParameter(

-        final java.lang.Object bean,

-        final org.apache.commons.validator.Form form,

-        final org.apache.commons.validator.Field field,

-        final org.apache.commons.validator.Validator validator,

-        final org.apache.commons.validator.ValidatorAction action,

-        final org.apache.commons.validator.ValidatorResults results,

-        final java.util.Locale locale)

-        throws Exception {

+    public static boolean validateParameter(final java.lang.Object bean, final org.apache.commons.validator.Form form,

+            final org.apache.commons.validator.Field field, final org.apache.commons.validator.Validator validator,

+            final org.apache.commons.validator.ValidatorAction action, final org.apache.commons.validator.ValidatorResults results,

+            final java.util.Locale locale) throws Exception {

 

         return true;

     }

diff --git a/src/test/java/org/apache/commons/validator/RequiredIfTest.java b/src/test/java/org/apache/commons/validator/RequiredIfTest.java
index 303dec9..ad6c72a 100644
--- a/src/test/java/org/apache/commons/validator/RequiredIfTest.java
+++ b/src/test/java/org/apache/commons/validator/RequiredIfTest.java
@@ -16,8 +16,14 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.IOException;
 
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
 /**
@@ -25,202 +31,200 @@
  */
 public class RequiredIfTest extends AbstractCommonTest {
 
-   /**
-    * The key used to retrieve the set of validation
-    * rules from the xml file.
-    */
-   protected static String FORM_KEY = "nameForm";
+    /**
+     * The key used to retrieve the set of validation rules from the xml file.
+     */
+    protected static String FORM_KEY = "nameForm";
 
-   /**
-    * The key used to retrieve the validator action.
-    */
-   protected static String ACTION = "requiredif";
+    /**
+     * The key used to retrieve the validator action.
+     */
+    protected static String ACTION = "requiredif";
 
-   public RequiredIfTest(final String name) {
-       super(name);
-   }
+    /**
+     * Load <code>ValidatorResources</code> from validator-requiredif.xml.
+     */
+    @BeforeEach
+    protected void setUp() throws IOException, SAXException {
+        // Load resources
+        loadResources("RequiredIfTest-config.xml");
+    }
 
-   /**
-    * Load <code>ValidatorResources</code> from
-    * validator-requiredif.xml.
-    */
-   @Override
-protected void setUp() throws IOException, SAXException {
-      // Load resources
-      loadResources("RequiredIfTest-config.xml");
-   }
+    @AfterEach
+    protected void tearDown() {
+    }
 
-   @Override
-protected void tearDown() {
-   }
+    /**
+     * With nothing provided, we should pass since the fields only fail on null if the other field is non-blank.
+     */
+    @Test
+    public void testRequired() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
 
-   /**
-    * With nothing provided, we should pass since the fields only fail on
-    * null if the other field is non-blank.
-    */
-   public void testRequired() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Get results of the validation.
+        // throws ValidatorException,
+        // but we aren't catching for testing
+        // since no validation methods we use
+        // throw this
+        final ValidatorResults results = validator.validate();
 
-      // Get results of the validation.
-      // throws ValidatorException,
-      // but we aren't catching for testing
-      // since no validation methods we use
-      // throw this
-      final ValidatorResults results = validator.validate();
+        assertNotNull(results, "Results are null.");
 
-      assertNotNull("Results are null.", results);
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have passed.", firstNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "Last Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), () -> "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(lastNameResult.isValid(ACTION), () -> "Last Name ValidatorResult for the '" + ACTION + "' action should have passed.");
+    }
 
-      assertNotNull("Last Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have passed.", lastNameResult.isValid(ACTION));
-   }
+    /**
+     * Tests the required validation for last name.
+     */
+    @Test
+    public void testRequiredFirstName() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("Test");
+        name.setLastName("Test");
 
-   /**
-    * Tests the required validation for first name if it is blank.
-    */
-   public void testRequiredFirstNameBlank() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setFirstName("");
-      name.setLastName("Test");
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        assertNotNull(results, "Results are null.");
 
-      assertNotNull("Results are null.", results);
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have failed.", !firstNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "Last Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), () -> "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(lastNameResult.isValid(ACTION), () -> "Last Name ValidatorResult for the '" + ACTION + "' action should have passed.");
+    }
 
-      assertNotNull("Last Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have passed.", lastNameResult.isValid(ACTION));
-   }
+    /**
+     * Tests the required validation for first name if it is blank.
+     */
+    @Test
+    public void testRequiredFirstNameBlank() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("");
+        name.setLastName("Test");
 
-   /**
-    * Tests the required validation for last name.
-    */
-   public void testRequiredFirstName() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setFirstName("Test");
-      name.setLastName("Test");
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        assertNotNull(results, "Results are null.");
 
-      assertNotNull("Results are null.", results);
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have failed.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have passed.", firstNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "Last Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), () -> "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(lastNameResult.isValid(ACTION), () -> "Last Name ValidatorResult for the '" + ACTION + "' action should have passed.");
+    }
 
-      assertNotNull("Last Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have passed.", lastNameResult.isValid(ACTION));
-   }
+    /**
+     * Tests the required validation for last name.
+     */
+    @Test
+    public void testRequiredLastName() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("Joe");
+        name.setLastName("Smith");
 
-   /**
-    * Tests the required validation for last name if it is blank.
-    */
-   public void testRequiredLastNameBlank() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setFirstName("Joe");
-      name.setLastName("");
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        assertNotNull(results, "Results are null.");
 
-      assertNotNull("Results are null.", results);
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(firstNameResult.isValid(ACTION), "First Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have passed.", firstNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "Last Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), () -> "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(lastNameResult.isValid(ACTION), () -> "Last Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-      assertNotNull("Last Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have failed.", !lastNameResult.isValid(ACTION));
-   }
+    }
 
-   /**
-    * Tests the required validation for last name.
-    */
-   public void testRequiredLastName() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setFirstName("Joe");
-      name.setLastName("Smith");
+    /**
+     * Tests the required validation for last name if it is blank.
+     */
+    @Test
+    public void testRequiredLastNameBlank() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("Joe");
+        name.setLastName("");
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-      assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have passed.", firstNameResult.isValid(ACTION));
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-      assertNotNull("Last Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have passed.", lastNameResult.isValid(ACTION));
-
-   }
+        assertNotNull(lastNameResult, "Last Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), () -> "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!lastNameResult.isValid(ACTION), () -> "Last Name ValidatorResult for the '" + ACTION + "' action should have failed.");
+    }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/RequiredNameTest.java b/src/test/java/org/apache/commons/validator/RequiredNameTest.java
index e09e1f9..0a8bdc9 100644
--- a/src/test/java/org/apache/commons/validator/RequiredNameTest.java
+++ b/src/test/java/org/apache/commons/validator/RequiredNameTest.java
@@ -16,240 +16,245 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.IOException;
 
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
-
 /**
  * Performs Validation Test.
  */
 public class RequiredNameTest extends AbstractCommonTest {
 
-   /**
-    * The key used to retrieve the set of validation
-    * rules from the xml file.
-    */
-   protected static String FORM_KEY = "nameForm";
+    /**
+     * The key used to retrieve the set of validation rules from the xml file.
+     */
+    protected static String FORM_KEY = "nameForm";
 
-   /**
-    * The key used to retrieve the validator action.
-    */
-   protected static String ACTION = "required";
+    /**
+     * The key used to retrieve the validator action.
+     */
+    protected static String ACTION = "required";
 
-   public RequiredNameTest(final String name) {
-       super(name);
-   }
+    /**
+     * Load <code>ValidatorResources</code> from validator-name-required.xml.
+     */
+    @BeforeEach
+    protected void setUp() throws IOException, SAXException {
+        // Load resources
+        loadResources("RequiredNameTest-config.xml");
+    }
 
-   /**
-    * Load <code>ValidatorResources</code> from
-    * validator-name-required.xml.
-    */
-   @Override
-protected void setUp() throws IOException, SAXException {
-      // Load resources
-      loadResources("RequiredNameTest-config.xml");
-   }
+    @AfterEach
+    protected void tearDown() {
+    }
 
-   @Override
-protected void tearDown() {
-   }
+    /**
+     * Tests the required validation failure.
+     */
+    @Test
+    public void testRequired() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
 
-   /**
-    * Tests the required validation failure.
-    */
-   public void testRequired() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Get results of the validation.
+        // throws ValidatorException,
+        // but we aren't catching for testing
+        // since no validation methods we use
+        // throw this
+        final ValidatorResults results = validator.validate();
 
-      // Get results of the validation.
-      // throws ValidatorException,
-      // but we aren't catching for testing
-      // since no validation methods we use
-      // throw this
-      final ValidatorResults results = validator.validate();
+        assertNotNull(results, "Results are null.");
 
-      assertNotNull("Results are null.", results);
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have failed.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have failed.", !firstNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!lastNameResult.isValid(ACTION), "Last Name ValidatorResult for the '" + ACTION + "' action should have failed.");
+    }
 
-      assertNotNull("First Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have failed.", !lastNameResult.isValid(ACTION));
-   }
+    /**
+     * Tests the required validation for first name.
+     */
+    @Test
+    public void testRequiredFirstName() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("Joe");
 
-   /**
-    * Tests the required validation for first name if it is blank.
-    */
-   public void testRequiredFirstNameBlank() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setFirstName("");
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        assertNotNull(results, "Results are null.");
 
-      assertNotNull("Results are null.", results);
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have failed.", !firstNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), () -> "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!lastNameResult.isValid(ACTION), () -> "Last Name ValidatorResult for the '" + ACTION + "' action should have failed.");
+    }
 
-      assertNotNull("First Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have failed.", !lastNameResult.isValid(ACTION));
-   }
+    /**
+     * Tests the required validation for first name if it is blank.
+     */
+    @Test
+    public void testRequiredFirstNameBlank() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("");
 
-   /**
-    * Tests the required validation for first name.
-    */
-   public void testRequiredFirstName() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setFirstName("Joe");
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        assertNotNull(results, "Results are null.");
 
-      assertNotNull("Results are null.", results);
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have failed.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have passed.", firstNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), () -> "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!lastNameResult.isValid(ACTION), () -> "Last Name ValidatorResult for the '" + ACTION + "' action should have failed.");
+    }
 
-      assertNotNull("First Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have failed.", !lastNameResult.isValid(ACTION));
-   }
+    /**
+     * Tests the required validation for last name.
+     */
+    @Test
+    public void testRequiredLastName() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setLastName("Smith");
 
-   /**
-    * Tests the required validation for last name if it is blank.
-    */
-   public void testRequiredLastNameBlank() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setLastName("");
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        assertNotNull(results, "Results are null.");
 
-      assertNotNull("Results are null.", results);
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have failed.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have failed.", !firstNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), () -> "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(lastNameResult.isValid(ACTION), () -> "Last Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have failed.", !lastNameResult.isValid(ACTION));
-   }
+    }
 
-   /**
-    * Tests the required validation for last name.
-    */
-   public void testRequiredLastName() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setLastName("Smith");
+    /**
+     * Tests the required validation for last name if it is blank.
+     */
+    @Test
+    public void testRequiredLastNameBlank() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setLastName("");
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-      assertNotNull("Results are null.", results);
+        assertNotNull(results, "Results are null.");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have failed.", !firstNameResult.isValid(ACTION));
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!firstNameResult.isValid(ACTION), "First Name ValidatorResult for the '" + ACTION + "' action should have failed.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have passed.", lastNameResult.isValid(ACTION));
+        assertNotNull(lastNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), () -> "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(!lastNameResult.isValid(ACTION), () -> "Last Name ValidatorResult for the '" + ACTION + "' action should have failed.");
+    }
 
-   }
+    /**
+     * Tests the required validation for first and last name.
+     */
+    @Test
+    public void testRequiredName() throws ValidatorException {
+        // Create bean to run test on.
+        final NameBean name = new NameBean();
+        name.setFirstName("Joe");
+        name.setLastName("Smith");
 
-   /**
-    * Tests the required validation for first and last name.
-    */
-   public void testRequiredName() throws ValidatorException {
-      // Create bean to run test on.
-      final NameBean name = new NameBean();
-      name.setFirstName("Joe");
-      name.setLastName("Smith");
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, name);
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, name);
+        // Get results of the validation.
+        final ValidatorResults results = validator.validate();
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
+        assertNotNull(results, "Results are null.");
 
-      assertNotNull("Results are null.", results);
+        final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
+        final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
 
-      final ValidatorResult firstNameResult = results.getValidatorResult("firstName");
-      final ValidatorResult lastNameResult = results.getValidatorResult("lastName");
+        assertNotNull(firstNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(firstNameResult.containsAction(ACTION), () -> "First Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(firstNameResult.isValid(ACTION), () -> "First Name ValidatorResult for the '" + ACTION + "' action should have passed.");
 
-      assertNotNull("First Name ValidatorResult should not be null.", firstNameResult);
-      assertTrue("First Name ValidatorResult should contain the '" + ACTION +"' action.", firstNameResult.containsAction(ACTION));
-      assertTrue("First Name ValidatorResult for the '" + ACTION +"' action should have passed.", firstNameResult.isValid(ACTION));
-
-      assertNotNull("First Name ValidatorResult should not be null.", lastNameResult);
-      assertTrue("Last Name ValidatorResult should contain the '" + ACTION +"' action.", lastNameResult.containsAction(ACTION));
-      assertTrue("Last Name ValidatorResult for the '" + ACTION +"' action should have passed.", lastNameResult.isValid(ACTION));
-   }
+        assertNotNull(lastNameResult, "First Name ValidatorResult should not be null.");
+        assertTrue(lastNameResult.containsAction(ACTION), () -> "Last Name ValidatorResult should contain the '" + ACTION + "' action.");
+        assertTrue(lastNameResult.isValid(ACTION), () -> "Last Name ValidatorResult for the '" + ACTION + "' action should have passed.");
+    }
 
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/ResultPair.java b/src/test/java/org/apache/commons/validator/ResultPair.java
index 2436cb4..14f5cae 100644
--- a/src/test/java/org/apache/commons/validator/ResultPair.java
+++ b/src/test/java/org/apache/commons/validator/ResultPair.java
@@ -14,17 +14,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
- package org.apache.commons.validator;
+package org.apache.commons.validator;
 
 /**
  * Groups tests and expected results.
  */
- public class ResultPair {
-      public final String item;
-      public final boolean valid;
+public class ResultPair {
+    public final String item;
+    public final boolean valid;
 
-      public ResultPair(final String item, final boolean valid) {
-         this.item = item;
-         this.valid = valid; // Whether the individual part of URL is valid.
-      }
-   }
+    public ResultPair(final String item, final boolean valid) {
+        this.item = item;
+        this.valid = valid; // Whether the individual part of URL is valid.
+    }
+}
diff --git a/src/test/java/org/apache/commons/validator/RetrieveFormTest.java b/src/test/java/org/apache/commons/validator/RetrieveFormTest.java
index 78ed3cd..05f80e4 100644
--- a/src/test/java/org/apache/commons/validator/RetrieveFormTest.java
+++ b/src/test/java/org/apache/commons/validator/RetrieveFormTest.java
@@ -16,23 +16,22 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Locale;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
-import junit.framework.TestCase;
-
 /**
  * Tests retrieving forms using different Locales.
  */
-public class RetrieveFormTest extends TestCase {
-
-    /**
-     * Resources used for validation tests.
-     */
-    private ValidatorResources resources;
+public class RetrieveFormTest {
 
     /**
      * Prefix for the forms.
@@ -45,22 +44,36 @@
     private static final Locale CANADA_FRENCH_XXX = new Locale("fr", "CA", "XXX");
 
     /**
-     * Constructor for FormTest.
-     * @param name
+     * Resources used for validation tests.
      */
-    public RetrieveFormTest(final String name) {
-        super(name);
+    private ValidatorResources resources;
+
+    private void checkForm(final Locale locale, final String formKey, final String expectedVarValue) {
+
+        // Retrieve the Form
+        final Form testForm = resources.getForm(locale, formKey);
+        assertNotNull(testForm, "Form '" + formKey + "' null for locale " + locale);
+
+        // Validate the expected Form is retrieved by checking the "localeVar"
+        // value of the field.
+        final Field testField = testForm.getField("testProperty");
+        assertEquals(expectedVarValue, testField.getVarValue("localeVar"), "Incorrect Form '" + formKey + "' for locale '" + locale + "'");
+    }
+
+    private void checkFormNotFound(final Locale locale, final String formKey) {
+
+        // Retrieve the Form
+        final Form testForm = resources.getForm(locale, formKey);
+        assertNull(testForm, "Form '" + formKey + "' not null for locale " + locale);
+
     }
 
     /**
      * Load <code>ValidatorResources</code> from multiple xml files.
      */
-    @Override
+    @BeforeEach
     protected void setUp() throws IOException, SAXException {
-        final InputStream[] streams =
-            {
-            this.getClass().getResourceAsStream(
-                "RetrieveFormTest-config.xml")};
+        final InputStream[] streams = { this.getClass().getResourceAsStream("RetrieveFormTest-config.xml") };
 
         this.resources = new ValidatorResources(streams);
 
@@ -69,9 +82,10 @@
         }
     }
 
-   /**
-    * Test a form defined only in the "default" formset.
-    */
+    /**
+     * Test a form defined only in the "default" formset.
+     */
+    @Test
     public void testDefaultForm() {
 
         final String formKey = FORM_PREFIX + "default";
@@ -96,39 +110,38 @@
 
     }
 
-   /**
-    * Test a form defined in the "default" formset and formsets
-    * where just the "language" is specified.
-    */
-    public void testLanguageForm() {
+    /**
+     * Test a form not defined
+     */
+    @Test
+    public void testFormNotFound() {
 
-        final String formKey = FORM_PREFIX + "language";
+        final String formKey = "INVALID_NAME";
 
         // *** US locale ***
-        checkForm(Locale.US, formKey, "default");
+        checkFormNotFound(Locale.US, formKey);
 
         // *** French locale ***
-        checkForm(Locale.FRENCH, formKey, "fr");
+        checkFormNotFound(Locale.FRENCH, formKey);
 
         // *** France locale ***
-        checkForm(Locale.FRANCE, formKey, "fr");
+        checkFormNotFound(Locale.FRANCE, formKey);
 
         // *** Candian (English) locale ***
-        checkForm(Locale.CANADA, formKey, "default");
+        checkFormNotFound(Locale.CANADA, formKey);
 
         // *** Candian French locale ***
-        checkForm(Locale.CANADA_FRENCH, formKey, "fr");
+        checkFormNotFound(Locale.CANADA_FRENCH, formKey);
 
         // *** Candian French Variant locale ***
-        checkForm(CANADA_FRENCH_XXX, formKey, "fr");
+        checkFormNotFound(CANADA_FRENCH_XXX, formKey);
 
     }
 
-   /**
-    * Test a form defined in the "default" formset, formsets
-    * where just the "language" is specified and formset where
-    * the language and country are specified.
-    */
+    /**
+     * Test a form defined in the "default" formset, formsets where just the "language" is specified and formset where the language and country are specified.
+     */
+    @Test
     public void testLanguageCountryForm() {
 
         final String formKey = FORM_PREFIX + "language_country";
@@ -153,9 +166,10 @@
 
     }
 
-   /**
-    * Test a form defined in all the formsets
-    */
+    /**
+     * Test a form defined in all the formsets
+     */
+    @Test
     public void testLanguageCountryVariantForm() {
 
         final String formKey = FORM_PREFIX + "language_country_variant";
@@ -180,53 +194,31 @@
 
     }
 
-   /**
-    * Test a form not defined
-    */
-    public void testFormNotFound() {
+    /**
+     * Test a form defined in the "default" formset and formsets where just the "language" is specified.
+     */
+    @Test
+    public void testLanguageForm() {
 
-        final String formKey = "INVALID_NAME";
+        final String formKey = FORM_PREFIX + "language";
 
         // *** US locale ***
-        checkFormNotFound(Locale.US, formKey);
+        checkForm(Locale.US, formKey, "default");
 
         // *** French locale ***
-        checkFormNotFound(Locale.FRENCH, formKey);
+        checkForm(Locale.FRENCH, formKey, "fr");
 
         // *** France locale ***
-        checkFormNotFound(Locale.FRANCE, formKey);
+        checkForm(Locale.FRANCE, formKey, "fr");
 
         // *** Candian (English) locale ***
-        checkFormNotFound(Locale.CANADA, formKey);
+        checkForm(Locale.CANADA, formKey, "default");
 
         // *** Candian French locale ***
-        checkFormNotFound(Locale.CANADA_FRENCH, formKey);
+        checkForm(Locale.CANADA_FRENCH, formKey, "fr");
 
         // *** Candian French Variant locale ***
-        checkFormNotFound(CANADA_FRENCH_XXX, formKey);
-
-
-    }
-
-    private void checkForm(final Locale locale, final String formKey, final String expectedVarValue) {
-
-        // Retrieve the Form
-        final Form testForm = resources.getForm(locale, formKey);
-        assertNotNull("Form '" +formKey+"' null for locale " + locale, testForm);
-
-        // Validate the expected Form is retrieved by checking the "localeVar"
-        // value of the field.
-        final Field testField = testForm.getField("testProperty");
-        assertEquals("Incorrect Form '"   + formKey  + "' for locale '" + locale + "'",
-                     expectedVarValue,
-                     testField.getVarValue("localeVar"));
-    }
-
-    private void checkFormNotFound(final Locale locale, final String formKey) {
-
-        // Retrieve the Form
-        final Form testForm = resources.getForm(locale, formKey);
-        assertNull("Form '" +formKey+"' not null for locale " + locale, testForm);
+        checkForm(CANADA_FRENCH_XXX, formKey, "fr");
 
     }
 
diff --git a/src/test/java/org/apache/commons/validator/ShortTest.java b/src/test/java/org/apache/commons/validator/ShortTest.java
index 85aa267..dfb623a 100644
--- a/src/test/java/org/apache/commons/validator/ShortTest.java
+++ b/src/test/java/org/apache/commons/validator/ShortTest.java
@@ -16,59 +16,63 @@
  */
 package org.apache.commons.validator;
 
+import org.junit.jupiter.api.Test;
 
 /**
  * Performs Validation Test for <code>short</code> validations.
  */
 public class ShortTest extends AbstractNumberTest {
 
-   public ShortTest(final String name) {
-       super(name);
-      FORM_KEY = "shortForm";
-      ACTION = "short";
-   }
+    public ShortTest() {
+        FORM_KEY = "shortForm";
+        ACTION = "short";
+    }
 
-   /**
-    * Tests the short validation.
-    */
-   public void testShortMin() throws ValidatorException {
-      // Create bean to run test on.
-      final ValueBean info = new ValueBean();
-      info.setValue(Short.toString(Short.MIN_VALUE));
+    /**
+     * Tests the short validation failure.
+     */
+    @Test
+    public void testShortBeyondMax() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+        info.setValue(Short.MAX_VALUE + "1");
 
-      valueTest(info, true);
-   }
+        valueTest(info, false);
+    }
 
-   /**
-    * Tests the short validation.
-    */
-   public void testShortMax() throws ValidatorException {
-      // Create bean to run test on.
-      final ValueBean info = new ValueBean();
-      info.setValue(Short.toString(Short.MAX_VALUE));
+    /**
+     * Tests the short validation failure.
+     */
+    @Test
+    public void testShortBeyondMin() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+        info.setValue(Short.MIN_VALUE + "1");
 
-      valueTest(info, true);
-   }
+        valueTest(info, false);
+    }
 
-   /**
-    * Tests the short validation failure.
-    */
-   public void testShortBeyondMin() throws ValidatorException {
-      // Create bean to run test on.
-      final ValueBean info = new ValueBean();
-      info.setValue(Short.MIN_VALUE + "1");
+    /**
+     * Tests the short validation.
+     */
+    @Test
+    public void testShortMax() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+        info.setValue(Short.toString(Short.MAX_VALUE));
 
-      valueTest(info, false);
-   }
+        valueTest(info, true);
+    }
 
-   /**
-    * Tests the short validation failure.
-    */
-   public void testShortBeyondMax() throws ValidatorException {
-      // Create bean to run test on.
-      final ValueBean info = new ValueBean();
-      info.setValue(Short.MAX_VALUE + "1");
+    /**
+     * Tests the short validation.
+     */
+    @Test
+    public void testShortMin() throws ValidatorException {
+        // Create bean to run test on.
+        final ValueBean info = new ValueBean();
+        info.setValue(Short.toString(Short.MIN_VALUE));
 
-      valueTest(info, false);
-   }
+        valueTest(info, true);
+    }
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/TypeBean.java b/src/test/java/org/apache/commons/validator/TypeBean.java
index 936c930..0c2e05e 100644
--- a/src/test/java/org/apache/commons/validator/TypeBean.java
+++ b/src/test/java/org/apache/commons/validator/TypeBean.java
@@ -17,8 +17,7 @@
 package org.apache.commons.validator;
 
 /**
- * Value object that contains different fields to test type conversion
- * validation.
+ * Value object that contains different fields to test type conversion validation.
  */
 public class TypeBean {
 
@@ -35,64 +34,64 @@
         return sByte;
     }
 
-    public void setByte(final String sByte) {
-        this.sByte = sByte;
-    }
-
-    public String getShort() {
-        return sShort;
-    }
-
-    public void setShort(final String sShort) {
-        this.sShort = sShort;
-    }
-
-    public String getInteger() {
-        return sInteger;
-    }
-
-    public void setInteger(final String sInteger) {
-        this.sInteger = sInteger;
-    }
-
-    public String getLong() {
-        return sLong;
-    }
-
-    public void setLong(final String sLong) {
-        this.sLong = sLong;
-    }
-
-    public String getFloat() {
-        return sFloat;
-    }
-
-    public void setFloat(final String sFloat) {
-        this.sFloat = sFloat;
-    }
-
-    public String getDouble() {
-        return sDouble;
-    }
-
-    public void setDouble(final String sDouble) {
-        this.sDouble = sDouble;
+    public String getCreditCard() {
+        return sCreditCard;
     }
 
     public String getDate() {
         return sDate;
     }
 
-    public void setDate(final String sDate) {
-        this.sDate = sDate;
+    public String getDouble() {
+        return sDouble;
     }
 
-    public String getCreditCard() {
-        return sCreditCard;
+    public String getFloat() {
+        return sFloat;
+    }
+
+    public String getInteger() {
+        return sInteger;
+    }
+
+    public String getLong() {
+        return sLong;
+    }
+
+    public String getShort() {
+        return sShort;
+    }
+
+    public void setByte(final String sByte) {
+        this.sByte = sByte;
     }
 
     public void setCreditCard(final String sCreditCard) {
         this.sCreditCard = sCreditCard;
     }
 
+    public void setDate(final String sDate) {
+        this.sDate = sDate;
+    }
+
+    public void setDouble(final String sDouble) {
+        this.sDouble = sDouble;
+    }
+
+    public void setFloat(final String sFloat) {
+        this.sFloat = sFloat;
+    }
+
+    public void setInteger(final String sInteger) {
+        this.sInteger = sInteger;
+    }
+
+    public void setLong(final String sLong) {
+        this.sLong = sLong;
+    }
+
+    public void setShort(final String sShort) {
+        this.sShort = sShort;
+    }
+
 }
diff --git a/src/test/java/org/apache/commons/validator/UrlTest.java b/src/test/java/org/apache/commons/validator/UrlTest.java
index 8ea7b21..b908d92 100644
--- a/src/test/java/org/apache/commons/validator/UrlTest.java
+++ b/src/test/java/org/apache/commons/validator/UrlTest.java
@@ -16,7 +16,11 @@
  */
 package org.apache.commons.validator;
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * Performs Validation Test for url validations.
@@ -24,257 +28,204 @@
  * @deprecated to be removed when org.apache.commons.validator.UrlValidator is removed
  */
 @Deprecated
-public class UrlTest extends TestCase {
+public class UrlTest {
 
-   private final boolean printStatus = false;
-   private final boolean printIndex = false;//print index that indicates current scheme,host,port,path, query test were using.
+    static boolean incrementTestPartsIndex(final int[] testPartsIndex, final Object[] testParts) {
+        boolean carry = true; // add 1 to lowest order part.
+        boolean maxIndex = true;
+        for (int testPartsIndexIndex = testPartsIndex.length - 1; testPartsIndexIndex >= 0; --testPartsIndexIndex) {
+            int index = testPartsIndex[testPartsIndexIndex];
+            final ResultPair[] part = (ResultPair[]) testParts[testPartsIndexIndex];
+            if (carry) {
+                if (index < part.length - 1) {
+                    index++;
+                    testPartsIndex[testPartsIndexIndex] = index;
+                    carry = false;
+                } else {
+                    testPartsIndex[testPartsIndexIndex] = 0;
+                    carry = true;
+                }
+            }
+            maxIndex &= index == part.length - 1;
+        }
 
-   public UrlTest(final String testName) {
-      super(testName);
-   }
+        return !maxIndex;
+    }
 
-   @Override
-protected void setUp() {
-      for (int index = 0; index < testPartsIndex.length - 1; index++) {
-         testPartsIndex[index] = 0;
-      }
-   }
+    /**
+     * Only used to debug the unit tests.
+     *
+     * @param argv
+     */
+    public static void main(final String[] argv) {
 
-   public void testIsValid() {
+        final UrlTest fct = new UrlTest();
+        fct.setUp();
+        fct.testIsValid();
+        fct.testIsValidScheme();
+    }
+
+    private final boolean printStatus = false;
+
+    private final boolean printIndex = false;// print index that indicates current scheme,host,port,path, query test were using.
+
+    /**
+     * The data given below approximates the 4 parts of a URL <scheme>://<authority><path>?<query> except that the port number is broken out of authority to
+     * increase the number of permutations. A complete URL is composed of a scheme+authority+port+path+query, all of which must be individually valid for the
+     * entire URL to be considered valid.
+     */
+    ResultPair[] testUrlScheme = { new ResultPair("http://", true), new ResultPair("ftp://", true), new ResultPair("h3t://", true),
+            new ResultPair("3ht://", false), new ResultPair("http:/", false), new ResultPair("http:", false), new ResultPair("http/", false),
+            new ResultPair("://", false), new ResultPair("", true) };
+
+    ResultPair[] testUrlAuthority = { new ResultPair("www.google.com", true), new ResultPair("go.com", true), new ResultPair("go.au", true),
+            new ResultPair("0.0.0.0", true), new ResultPair("255.255.255.255", true), new ResultPair("256.256.256.256", false), new ResultPair("255.com", true),
+            new ResultPair("1.2.3.4.5", false), new ResultPair("1.2.3.4.", false), new ResultPair("1.2.3", false), new ResultPair(".1.2.3.4", false),
+            new ResultPair("go.a", false), new ResultPair("go.a1a", true), new ResultPair("go.1aa", false), new ResultPair("aaa.", false),
+            new ResultPair(".aaa", false), new ResultPair("aaa", false), new ResultPair("", false) };
+
+    ResultPair[] testUrlPort = { new ResultPair(":80", true), new ResultPair(":65535", true), new ResultPair(":0", true), new ResultPair("", true),
+            new ResultPair(":-1", false), new ResultPair(":65636", true), new ResultPair(":65a", false) };
+
+    ResultPair[] testPath = { new ResultPair("/test1", true), new ResultPair("/t123", true), new ResultPair("/$23", true), new ResultPair("/..", false),
+            new ResultPair("/../", false), new ResultPair("/test1/", true), new ResultPair("", true), new ResultPair("/test1/file", true),
+            new ResultPair("/..//file", false), new ResultPair("/test1//file", false) };
+
+    // Test allow2slash, noFragment
+    ResultPair[] testUrlPathOptions = { new ResultPair("/test1", true), new ResultPair("/t123", true), new ResultPair("/$23", true),
+            new ResultPair("/..", false), new ResultPair("/../", false), new ResultPair("/test1/", true), new ResultPair("/#", false), new ResultPair("", true),
+            new ResultPair("/test1/file", true), new ResultPair("/t123/file", true), new ResultPair("/$23/file", true), new ResultPair("/../file", false),
+            new ResultPair("/..//file", false), new ResultPair("/test1//file", true), new ResultPair("/#/file", false) };
+
+    ResultPair[] testUrlQuery = { new ResultPair("?action=view", true), new ResultPair("?action=edit&mode=up", true), new ResultPair("", true) };
+
+    Object[] testUrlParts = { testUrlScheme, testUrlAuthority, testUrlPort, testPath, testUrlQuery };
+
+    Object[] testUrlPartsOptions = { testUrlScheme, testUrlAuthority, testUrlPort, testUrlPathOptions, testUrlQuery };
+
+    int[] testPartsIndex = { 0, 0, 0, 0, 0 };
+    // Test data for individual url parts
+    ResultPair[] testScheme = { new ResultPair("http", true), new ResultPair("ftp", false), new ResultPair("httpd", false), new ResultPair("telnet", false) };
+
+    @BeforeEach
+    protected void setUp() {
+        for (int index = 0; index < testPartsIndex.length - 1; index++) {
+            testPartsIndex[index] = 0;
+        }
+    }
+
+    @Test
+    public void testIsValid() {
         testIsValid(testUrlParts, UrlValidator.ALLOW_ALL_SCHEMES);
         setUp();
-        final int options =
-            UrlValidator.ALLOW_2_SLASHES
-                + UrlValidator.ALLOW_ALL_SCHEMES
-                + UrlValidator.NO_FRAGMENTS;
+        final int options = UrlValidator.ALLOW_2_SLASHES + UrlValidator.ALLOW_ALL_SCHEMES + UrlValidator.NO_FRAGMENTS;
 
         testIsValid(testUrlPartsOptions, options);
-   }
+    }
 
-   public void testIsValidScheme() {
-      if (printStatus) {
-         System.out.print("\n testIsValidScheme() ");
-      }
-      final String[] schemes = {"http", "gopher"};
-      //UrlValidator urlVal = new UrlValidator(schemes,false,false,false);
-      final UrlValidator urlVal = new UrlValidator(schemes, 0);
-      for (final ResultPair testPair : testScheme) {
-         final boolean result = urlVal.isValidScheme(testPair.item);
-         assertEquals(testPair.item, testPair.valid, result);
-         if (printStatus) {
-            if (result == testPair.valid) {
-               System.out.print('.');
+    /**
+     * Create set of tests by taking the testUrlXXX arrays and running through all possible permutations of their combinations.
+     *
+     * @param testObjects Used to create a url.
+     */
+    void testIsValid(final Object[] testObjects, final int options) {
+        final UrlValidator urlVal = new UrlValidator(null, options);
+        assertTrue(urlVal.isValid("http://www.google.com"));
+        assertTrue(urlVal.isValid("http://www.google.com/"));
+        int statusPerLine = 60;
+        int printed = 0;
+        if (printIndex) {
+            statusPerLine = 6;
+        }
+        do {
+            final StringBuilder testBuffer = new StringBuilder();
+            boolean expected = true;
+            for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) {
+                final int index = testPartsIndex[testPartsIndexIndex];
+                final ResultPair[] part = (ResultPair[]) testObjects[testPartsIndexIndex];
+                testBuffer.append(part[index].item);
+                expected &= part[index].valid;
+            }
+            final String url = testBuffer.toString();
+            final boolean result = urlVal.isValid(url);
+            assertEquals(expected, result, url);
+            if (printStatus) {
+                if (printIndex) {
+                    System.out.print(testPartsIndextoString());
+                } else if (result == expected) {
+                    System.out.print('.');
+                } else {
+                    System.out.print('X');
+                }
+                printed++;
+                if (printed == statusPerLine) {
+                    System.out.println();
+                    printed = 0;
+                }
+            }
+        } while (incrementTestPartsIndex(testPartsIndex, testObjects));
+        if (printStatus) {
+            System.out.println();
+        }
+    }
+
+    @Test
+    public void testIsValidScheme() {
+        if (printStatus) {
+            System.out.print("\n testIsValidScheme() ");
+        }
+        final String[] schemes = { "http", "gopher" };
+        // UrlValidator urlVal = new UrlValidator(schemes,false,false,false);
+        final UrlValidator urlVal = new UrlValidator(schemes, 0);
+        for (final ResultPair testPair : testScheme) {
+            final boolean result = urlVal.isValidScheme(testPair.item);
+            assertEquals(testPair.valid, result, testPair.item);
+            if (printStatus) {
+                if (result == testPair.valid) {
+                    System.out.print('.');
+                } else {
+                    System.out.print('X');
+                }
+            }
+        }
+        if (printStatus) {
+            System.out.println();
+        }
+
+    }
+
+    private String testPartsIndextoString() {
+        final StringBuilder carryMsg = new StringBuilder("{");
+        for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) {
+            carryMsg.append(testPartsIndex[testPartsIndexIndex]);
+            if (testPartsIndexIndex < testPartsIndex.length - 1) {
+                carryMsg.append(',');
             } else {
-               System.out.print('X');
+                carryMsg.append('}');
             }
-         }
-      }
-      if (printStatus) {
-         System.out.println();
-      }
+        }
+        return carryMsg.toString();
 
-   }
+    }
 
-   /**
-    * Create set of tests by taking the testUrlXXX arrays and
-    * running through all possible permutations of their combinations.
-    *
-    * @param testObjects Used to create a url.
-    */
-   public void testIsValid(final Object[] testObjects, final int options) {
-      final UrlValidator urlVal = new UrlValidator(null, options);
-      assertTrue(urlVal.isValid("http://www.google.com"));
-      assertTrue(urlVal.isValid("http://www.google.com/"));
-      int statusPerLine = 60;
-      int printed = 0;
-      if (printIndex)  {
-         statusPerLine = 6;
-      }
-      do {
-          final StringBuilder testBuffer = new StringBuilder();
-         boolean expected = true;
-         for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) {
-            final int index = testPartsIndex[testPartsIndexIndex];
-            final ResultPair[] part = (ResultPair[]) testObjects[testPartsIndexIndex];
-            testBuffer.append(part[index].item);
-            expected &= part[index].valid;
-         }
-         final String url = testBuffer.toString();
-         final boolean result = urlVal.isValid(url);
-         assertEquals(url, expected, result);
-         if (printStatus) {
-            if (printIndex) {
-               System.out.print(testPartsIndextoString());
-            } else if (result == expected) {
-                  System.out.print('.');
-               } else {
-                  System.out.print('X');
-               }
-            printed++;
-            if (printed == statusPerLine) {
-               System.out.println();
-               printed = 0;
-            }
-         }
-      } while (incrementTestPartsIndex(testPartsIndex, testObjects));
-      if (printStatus) {
-         System.out.println();
-      }
-   }
+    @Test
+    public void testValidateUrl() {
+        assertTrue(true);
+    }
 
-   public void testValidator202() {
-       final String[] schemes = {"http","https"};
-       final UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.NO_FRAGMENTS);
-       urlValidator.isValid("http://www.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.log");
-   }
+    @Test
+    public void testValidator202() {
+        final String[] schemes = { "http", "https" };
+        final UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.NO_FRAGMENTS);
+        urlValidator.isValid(
+                "http://www.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.logoworks.comwww.log");
+    }
 
-   public void testValidator204() {
-       final String[] schemes = {"http","https"};
-       final UrlValidator urlValidator = new UrlValidator(schemes);
-       assertTrue(urlValidator.isValid("http://tech.yahoo.com/rc/desktops/102;_ylt=Ao8yevQHlZ4On0O3ZJGXLEQFLZA5"));
-   }
-
-   static boolean incrementTestPartsIndex(final int[] testPartsIndex, final Object[] testParts) {
-      boolean carry = true;  //add 1 to lowest order part.
-      boolean maxIndex = true;
-      for (int testPartsIndexIndex = testPartsIndex.length - 1; testPartsIndexIndex >= 0; --testPartsIndexIndex) {
-         int index = testPartsIndex[testPartsIndexIndex];
-         final ResultPair[] part = (ResultPair[]) testParts[testPartsIndexIndex];
-         if (carry) {
-            if (index < part.length - 1) {
-               index++;
-               testPartsIndex[testPartsIndexIndex] = index;
-               carry = false;
-            } else {
-               testPartsIndex[testPartsIndexIndex] = 0;
-               carry = true;
-            }
-         }
-         maxIndex &= (index == (part.length - 1));
-      }
-
-
-      return (!maxIndex);
-   }
-
-   private String testPartsIndextoString() {
-       final StringBuilder carryMsg = new StringBuilder("{");
-      for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) {
-         carryMsg.append(testPartsIndex[testPartsIndexIndex]);
-         if (testPartsIndexIndex < testPartsIndex.length - 1) {
-            carryMsg.append(',');
-         } else {
-            carryMsg.append('}');
-         }
-      }
-      return carryMsg.toString();
-
-   }
-
-   public void testValidateUrl() {
-      assertTrue(true);
-   }
-
-   /**
-    * Only used to debug the unit tests.
-    * @param argv
-    */
-   public static void main(final String[] argv) {
-
-      final UrlTest fct = new UrlTest("url test");
-      fct.setUp();
-      fct.testIsValid();
-      fct.testIsValidScheme();
-   }
-   //-------------------- Test data for creating a composite URL
-   /**
-    * The data given below approximates the 4 parts of a URL
-    * <scheme>://<authority><path>?<query> except that the port number
-    * is broken out of authority to increase the number of permutations.
-    * A complete URL is composed of a scheme+authority+port+path+query,
-    * all of which must be individually valid for the entire URL to be considered
-    * valid.
-    */
-   ResultPair[] testUrlScheme = {new ResultPair("http://", true),
-                               new ResultPair("ftp://", true),
-                               new ResultPair("h3t://", true),
-                               new ResultPair("3ht://", false),
-                               new ResultPair("http:/", false),
-                               new ResultPair("http:", false),
-                               new ResultPair("http/", false),
-                               new ResultPair("://", false),
-                               new ResultPair("", true)};
-
-   ResultPair[] testUrlAuthority = {new ResultPair("www.google.com", true),
-                                  new ResultPair("go.com", true),
-                                  new ResultPair("go.au", true),
-                                  new ResultPair("0.0.0.0", true),
-                                  new ResultPair("255.255.255.255", true),
-                                  new ResultPair("256.256.256.256", false),
-                                  new ResultPair("255.com", true),
-                                  new ResultPair("1.2.3.4.5", false),
-                                  new ResultPair("1.2.3.4.", false),
-                                  new ResultPair("1.2.3", false),
-                                  new ResultPair(".1.2.3.4", false),
-                                  new ResultPair("go.a", false),
-                                  new ResultPair("go.a1a", true),
-                                  new ResultPair("go.1aa", false),
-                                  new ResultPair("aaa.", false),
-                                  new ResultPair(".aaa", false),
-                                  new ResultPair("aaa", false),
-                                  new ResultPair("", false)
-   };
-   ResultPair[] testUrlPort = {new ResultPair(":80", true),
-                             new ResultPair(":65535", true),
-                             new ResultPair(":0", true),
-                             new ResultPair("", true),
-                             new ResultPair(":-1", false),
-                             new ResultPair(":65636", true),
-                             new ResultPair(":65a", false)
-   };
-   ResultPair[] testPath = {new ResultPair("/test1", true),
-                          new ResultPair("/t123", true),
-                          new ResultPair("/$23", true),
-                          new ResultPair("/..", false),
-                          new ResultPair("/../", false),
-                          new ResultPair("/test1/", true),
-                          new ResultPair("", true),
-                          new ResultPair("/test1/file", true),
-                          new ResultPair("/..//file", false),
-                          new ResultPair("/test1//file", false)
-   };
-   //Test allow2slash, noFragment
-   ResultPair[] testUrlPathOptions = {new ResultPair("/test1", true),
-                                    new ResultPair("/t123", true),
-                                    new ResultPair("/$23", true),
-                                    new ResultPair("/..", false),
-                                    new ResultPair("/../", false),
-                                    new ResultPair("/test1/", true),
-                                    new ResultPair("/#", false),
-                                    new ResultPair("", true),
-                                    new ResultPair("/test1/file", true),
-                                    new ResultPair("/t123/file", true),
-                                    new ResultPair("/$23/file", true),
-                                    new ResultPair("/../file", false),
-                                    new ResultPair("/..//file", false),
-                                    new ResultPair("/test1//file", true),
-                                    new ResultPair("/#/file", false)
-   };
-
-   ResultPair[] testUrlQuery = {new ResultPair("?action=view", true),
-                              new ResultPair("?action=edit&mode=up", true),
-                              new ResultPair("", true)
-   };
-
-   Object[] testUrlParts = {testUrlScheme, testUrlAuthority, testUrlPort, testPath, testUrlQuery};
-   Object[] testUrlPartsOptions = {testUrlScheme, testUrlAuthority, testUrlPort, testUrlPathOptions, testUrlQuery};
-   int[] testPartsIndex = {0, 0, 0, 0, 0};
-
-   //---------------- Test data for individual url parts ----------------
-   ResultPair[] testScheme = {new ResultPair("http", true),
-                            new ResultPair("ftp", false),
-                            new ResultPair("httpd", false),
-                            new ResultPair("telnet", false)};
-
+    @Test
+    public void testValidator204() {
+        final String[] schemes = { "http", "https" };
+        final UrlValidator urlValidator = new UrlValidator(schemes);
+        assertTrue(urlValidator.isValid("http://tech.yahoo.com/rc/desktops/102;_ylt=Ao8yevQHlZ4On0O3ZJGXLEQFLZA5"));
+    }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/ValidatorResourcesTest.java b/src/test/java/org/apache/commons/validator/ValidatorResourcesTest.java
index 612aff4..e9421dc 100644
--- a/src/test/java/org/apache/commons/validator/ValidatorResourcesTest.java
+++ b/src/test/java/org/apache/commons/validator/ValidatorResourcesTest.java
@@ -16,31 +16,27 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.io.InputStream;
 
-import junit.framework.TestCase;
+import org.junit.jupiter.api.Test;
 
 /**
  * Test ValidatorResources.
  */
-public class ValidatorResourcesTest extends TestCase {
-
-    /**
-     * Constructor.
-     */
-    public ValidatorResourcesTest(final String name) {
-        super(name);
-    }
+public class ValidatorResourcesTest {
 
     /**
      * Test null Input Stream for Validator Resources.
      */
+    @Test
     public void testNullInputStream() throws Exception {
 
         try {
-            new ValidatorResources((InputStream)null);
+            new ValidatorResources((InputStream) null);
             fail("Expected IllegalArgumentException");
-        } catch(final IllegalArgumentException e) {
+        } catch (final IllegalArgumentException e) {
             // expected result
             // System.out.println("Exception: " + e);
         }
diff --git a/src/test/java/org/apache/commons/validator/ValidatorResultsTest.java b/src/test/java/org/apache/commons/validator/ValidatorResultsTest.java
index 188c662..9074b47 100644
--- a/src/test/java/org/apache/commons/validator/ValidatorResultsTest.java
+++ b/src/test/java/org/apache/commons/validator/ValidatorResultsTest.java
@@ -16,8 +16,16 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.IOException;
 
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
 /**
@@ -25,137 +33,128 @@
  */
 public class ValidatorResultsTest extends AbstractCommonTest {
 
-   private static final String FORM_KEY = "nameForm";
-   private static final String firstNameField  = "firstName";
-   private static final String middleNameField = "middleName";
-   private static final String lastNameField   = "lastName";
+    private static final String FORM_KEY = "nameForm";
+    private static final String firstNameField = "firstName";
+    private static final String middleNameField = "middleName";
+    private static final String lastNameField = "lastName";
 
-   private String firstName;
-   private String middleName;
-   private String lastName;
+    private String firstName;
+    private String middleName;
+    private String lastName;
 
-   /**
-    * Constructor.
-    */
-   public ValidatorResultsTest(final String name) {
-       super(name);
-   }
+    /**
+     * Check a validator has not been run for a field and the result.
+     */
+    private void checkNotRun(final ValidatorResults results, final String field, final String action) {
+        final ValidatorResult result = results.getValidatorResult(field);
+        assertNotNull(result, () -> field + " result");
+        assertFalse(result.containsAction(action), () -> field + "[" + action + "] run");
+        // System.out.println(field + "[" + action + "] not run");
+    }
 
-   /**
-    * Load <code>ValidatorResources</code> from
-    * ValidatorResultsTest-config.xml.
-    */
-   @Override
-protected void setUp() throws IOException, SAXException {
-      // Load resources
-      loadResources("ValidatorResultsTest-config.xml");
+    /**
+     * Check a validator has run for a field and the result.
+     */
+    private void checkValidatorResult(final ValidatorResults results, final String field, final String action, final boolean expected) {
+        final ValidatorResult result = results.getValidatorResult(field);
+        // System.out.println(field + "[" + action + "]=" + result.isValid(action));
+        assertNotNull(result, () -> field + " result");
+        assertTrue(result.containsAction(action), () -> field + "[" + action + "] not run");
+        assertEquals(expected, result.isValid(action), () -> field + "[" + action + "] result");
+    }
 
-      // initialize values
-      firstName  = "foo";
-      middleName = "123";
-      lastName   = "456";
+    /**
+     * Create a NameBean.
+     */
+    private NameBean createNameBean() {
+        final NameBean name = new NameBean();
+        name.setFirstName(firstName);
+        name.setMiddleName(middleName);
+        name.setLastName(lastName);
+        return name;
+    }
 
-   }
+    /**
+     * Load <code>ValidatorResources</code> from ValidatorResultsTest-config.xml.
+     */
+    @BeforeEach
+    protected void setUp() throws IOException, SAXException {
+        // Load resources
+        loadResources("ValidatorResultsTest-config.xml");
 
-   @Override
-protected void tearDown() {
-   }
+        // initialize values
+        firstName = "foo";
+        middleName = "123";
+        lastName = "456";
 
-   /**
-    * Test all validations ran and passed.
-    */
-   public void testAllValid() throws ValidatorException {
+    }
 
-      // Create bean to run test on.
-      final NameBean bean = createNameBean();
+    @AfterEach
+    protected void tearDown() {
+    }
 
-      // Validate.
-      final ValidatorResults results = validate(bean);
+    /**
+     * Test all validations ran and passed.
+     */
+    @Test
+    public void testAllValid() throws ValidatorException {
 
-      // Check results
-      checkValidatorResult(results, firstNameField,  "required", true);
-      checkValidatorResult(results, middleNameField, "required", true);
-      checkValidatorResult(results, middleNameField, "int",      true);
-      checkValidatorResult(results, middleNameField, "positive", true);
-      checkValidatorResult(results, lastNameField,   "required", true);
-      checkValidatorResult(results, lastNameField,   "int",      true);
+        // Create bean to run test on.
+        final NameBean bean = createNameBean();
 
-   }
+        // Validate.
+        final ValidatorResults results = validate(bean);
 
-   /**
-    * Test some validations failed and some didn't run.
-    */
-   public void testErrors() throws ValidatorException {
+        // Check results
+        checkValidatorResult(results, firstNameField, "required", true);
+        checkValidatorResult(results, middleNameField, "required", true);
+        checkValidatorResult(results, middleNameField, "int", true);
+        checkValidatorResult(results, middleNameField, "positive", true);
+        checkValidatorResult(results, lastNameField, "required", true);
+        checkValidatorResult(results, lastNameField, "int", true);
 
-      middleName = "XXX";
-      lastName = null;
+    }
 
-      // Create bean to run test on.
-      final NameBean bean = createNameBean();
+    /**
+     * Test some validations failed and some didn't run.
+     */
+    @Test
+    public void testErrors() throws ValidatorException {
 
-      // Validate.
-      final ValidatorResults results = validate(bean);
+        middleName = "XXX";
+        lastName = null;
 
-      // Check results
-      checkValidatorResult(results, firstNameField,  "required", true);
-      checkValidatorResult(results, middleNameField, "required", true);
-      checkValidatorResult(results, middleNameField, "int",      false);
-      checkNotRun(results, middleNameField, "positive");
-      checkValidatorResult(results, lastNameField,   "required", false);
-      checkNotRun(results, lastNameField,   "int");
+        // Create bean to run test on.
+        final NameBean bean = createNameBean();
 
-   }
+        // Validate.
+        final ValidatorResults results = validate(bean);
 
-   /**
-    * Check a validator has not been run for a field and the result.
-    */
-   private void checkNotRun(final ValidatorResults results, final String field, final String action) {
-      final ValidatorResult result = results.getValidatorResult(field);
-      assertNotNull(field + " result",  result);
-      assertFalse(field + "[" + action + "] run", result.containsAction(action));
-      // System.out.println(field + "[" + action + "] not run");
-   }
+        // Check results
+        checkValidatorResult(results, firstNameField, "required", true);
+        checkValidatorResult(results, middleNameField, "required", true);
+        checkValidatorResult(results, middleNameField, "int", false);
+        checkNotRun(results, middleNameField, "positive");
+        checkValidatorResult(results, lastNameField, "required", false);
+        checkNotRun(results, lastNameField, "int");
 
-   /**
-    * Check a validator has run for a field and the result.
-    */
-   private void checkValidatorResult(final ValidatorResults results, final String field, final String action, final boolean expected) {
-      final ValidatorResult result = results.getValidatorResult(field);
-      // System.out.println(field + "[" + action + "]=" + result.isValid(action));
-      assertNotNull(field + " result",  result);
-      assertTrue(field + "[" + action + "] not run", result.containsAction(action));
-      assertEquals(field + "[" + action + "] result", expected, result.isValid(action));
-   }
+    }
 
-   /**
-    * Create a NameBean.
-    */
-   private NameBean createNameBean() {
-      final NameBean name = new NameBean();
-      name.setFirstName(firstName);
-      name.setMiddleName(middleName);
-      name.setLastName(lastName);
-      return name;
-   }
+    /**
+     * Validate results.
+     */
+    private ValidatorResults validate(final Object bean) throws ValidatorException {
 
-   /**
-    * Validate results.
-    */
-   private ValidatorResults validate(final Object bean) throws ValidatorException  {
+        // Construct validator based on the loaded resources
+        // and the form key
+        final Validator validator = new Validator(resources, FORM_KEY);
 
-      // Construct validator based on the loaded resources
-      // and the form key
-      final Validator validator = new Validator(resources, FORM_KEY);
+        // add the name bean to the validator as a resource
+        // for the validations to be performed on.
+        validator.setParameter(Validator.BEAN_PARAM, bean);
 
-      // add the name bean to the validator as a resource
-      // for the validations to be performed on.
-      validator.setParameter(Validator.BEAN_PARAM, bean);
+        return validator.validate();
 
-      // Get results of the validation.
-      final ValidatorResults results = validator.validate();
-
-      return results;
-
-   }
+    }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/ValidatorTest.java b/src/test/java/org/apache/commons/validator/ValidatorTest.java
index 138d732..56a7097 100644
--- a/src/test/java/org/apache/commons/validator/ValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/ValidatorTest.java
@@ -16,6 +16,12 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.text.DateFormat;
 import java.text.ParseException;
 import java.util.ArrayList;
@@ -24,118 +30,70 @@
 import java.util.Locale;
 
 import org.apache.commons.validator.util.ValidatorUtils;
-
-import junit.framework.TestCase;
+import org.junit.jupiter.api.Test;
 
 /**
  * Performs Validation Test.
  */
-public class ValidatorTest extends TestCase {
+public class ValidatorTest {
 
-   public ValidatorTest(final String name) {
-       super(name);
-   }
+    public static class TestBean {
+        private String letter;
+        private String date;
 
-   /**
-    * Verify that one value generates an error and the other passes.  The validation
-    * method being tested returns an object (<code>null</code> will be considered an error).
-    */
-   public void testManualObject() {
-        //     property name of the method we are validating
-        final String property = "date";
-        // name of ValidatorAction
-        final String action = "date";
-        final ValidatorResources resources = setupDateResources(property, action);
+        public String getDate() {
+            return date;
+        }
 
-      final TestBean bean = new TestBean();
-      bean.setDate("2/3/1999");
+        public String getLetter() {
+            return letter;
+        }
 
-      final Validator validator = new Validator(resources, "testForm");
-      validator.setParameter(Validator.BEAN_PARAM, bean);
+        public void setDate(final String date) {
+            this.date = date;
+        }
 
-      try {
-         final ValidatorResults results = validator.validate();
+        public void setLetter(final String letter) {
+            this.letter = letter;
+        }
+    }
 
-         assertNotNull("Results are null.", results);
+    /**
+     * Formats a <code>String</code> to a <code>Date</code>. The <code>Validator</code> will interpret a {@code null} as validation having failed.
+     */
+    public static Date formatDate(final Object bean, final Field field) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+        Date date = null;
 
-         final ValidatorResult result = results.getValidatorResult(property);
+        try {
+            final DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
 
-         assertNotNull("Results are null.", results);
+            formatter.setLenient(false);
 
-         assertTrue("ValidatorResult does not contain '" + action + "' validator result.", result.containsAction(action));
+            date = formatter.parse(value);
+        } catch (final ParseException e) {
+            System.out.println("ValidatorTest.formatDate() - " + e.getMessage());
+        }
 
-         assertTrue("Validation of the date formatting has failed.", result.isValid(action));
-      } catch (final Exception e) {
-         fail("An exception was thrown while calling Validator.validate()");
-      }
+        return date;
+    }
 
-      bean.setDate("2/30/1999");
+    /**
+     * Checks if the field is one upper case letter between 'A' and 'Z'.
+     */
+    public static boolean isCapLetter(final Object bean, final Field field, final List<String> l) {
+        final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
 
-      try {
-         final ValidatorResults results = validator.validate();
-
-         assertNotNull("Results are null.", results);
-
-         final ValidatorResult result = results.getValidatorResult(property);
-
-         assertNotNull("Results are null.", results);
-
-         assertTrue("ValidatorResult does not contain '" + action + "' validator result.", result.containsAction(action));
-
-         assertTrue("Validation of the date formatting has passed when it should have failed.", !result.isValid(action));
-      } catch (final Exception e) {
-         fail("An exception was thrown while calling Validator.validate()");
-      }
-
-   }
-
-   public void testOnlyReturnErrors() throws ValidatorException {
-        //     property name of the method we are validating
-        final String property = "date";
-        // name of ValidatorAction
-        final String action = "date";
-        final ValidatorResources resources = setupDateResources(property, action);
-
-        final TestBean bean = new TestBean();
-        bean.setDate("2/3/1999");
-
-        final Validator validator = new Validator(resources, "testForm");
-        validator.setParameter(Validator.BEAN_PARAM, bean);
-
-        ValidatorResults results = validator.validate();
-
-        assertNotNull(results);
-
-        // Field passed and should be in results
-        assertTrue(results.getPropertyNames().contains(property));
-
-        // Field passed but should not be in results
-        validator.setOnlyReturnErrors(true);
-        results = validator.validate();
-        assertFalse(results.getPropertyNames().contains(property));
-   }
-
-   public void testOnlyValidateField() throws ValidatorException {
-        //     property name of the method we are validating
-        final String property = "date";
-        // name of ValidatorAction
-        final String action = "date";
-        final ValidatorResources resources = setupDateResources(property, action);
-
-        final TestBean bean = new TestBean();
-        bean.setDate("2/3/1999");
-
-        final Validator validator = new Validator(resources, "testForm", property);
-        validator.setParameter(Validator.BEAN_PARAM, bean);
-
-        final ValidatorResults results = validator.validate();
-
-        assertNotNull(results);
-
-        // Field passed and should be in results
-        assertTrue(results.getPropertyNames().contains(property));
-   }
-
+        if (value == null || value.length() != 1) {
+            l.add("Error");
+            return false;
+        }
+        if (value.charAt(0) >= 'A' && value.charAt(0) <= 'Z') {
+            return true;
+        }
+        l.add("Error");
+        return false;
+    }
 
     private ValidatorResources setupDateResources(final String property, final String action) {
 
@@ -163,119 +121,217 @@
         return resources;
     }
 
-   /**
-    * Verify that one value generates an error and the other passes.  The validation
-    * method being tested returns a <code>boolean</code> value.
-    */
-   public void testManualBoolean() {
-      final ValidatorResources resources = new ValidatorResources();
+    /**
+     * Verify that one value generates an error and the other passes. The validation method being tested returns a <code>boolean</code> value.
+     */
+    @Test
+    public void testManualBoolean() {
+        final ValidatorResources resources = new ValidatorResources();
 
-      final ValidatorAction va = new ValidatorAction();
-      va.setName("capLetter");
-      va.setClassname("org.apache.commons.validator.ValidatorTest");
-      va.setMethod("isCapLetter");
-      va.setMethodParams("java.lang.Object,org.apache.commons.validator.Field,java.util.List");
+        final ValidatorAction va = new ValidatorAction();
+        va.setName("capLetter");
+        va.setClassName("org.apache.commons.validator.ValidatorTest");
+        va.setMethod("isCapLetter");
+        va.setMethodParams("java.lang.Object,org.apache.commons.validator.Field,java.util.List");
 
-      final FormSet fs = new FormSet();
-      final Form form = new Form();
-      form.setName("testForm");
-      final Field field = new Field();
-      field.setProperty("letter");
-      field.setDepends("capLetter");
-      form.addField(field);
-      fs.addForm(form);
+        final FormSet fs = new FormSet();
+        final Form form = new Form();
+        form.setName("testForm");
+        final Field field = new Field();
+        field.setProperty("letter");
+        field.setDepends("capLetter");
+        form.addField(field);
+        fs.addForm(form);
 
-      resources.addValidatorAction(va);
-      resources.addFormSet(fs);
-      resources.process();
+        resources.addValidatorAction(va);
+        resources.addFormSet(fs);
+        resources.process();
 
-      final List<?> l = new ArrayList<>();
+        final List<?> l = new ArrayList<>();
 
-      final TestBean bean = new TestBean();
-      bean.setLetter("A");
+        final TestBean bean = new TestBean();
+        bean.setLetter("A");
 
-      final Validator validator = new Validator(resources, "testForm");
-      validator.setParameter(Validator.BEAN_PARAM, bean);
-      validator.setParameter("java.util.List", l);
+        final Validator validator = new Validator(resources, "testForm");
+        validator.setParameter(Validator.BEAN_PARAM, bean);
+        validator.setParameter("java.util.List", l);
 
-      try {
-         validator.validate();
-      } catch (final Exception e) {
-         fail("An exception was thrown while calling Validator.validate()");
-      }
+        try {
+            validator.validate();
+        } catch (final Exception e) {
+            fail("An exception was thrown while calling Validator.validate()");
+        }
 
-      assertEquals("Validation of the letter 'A'.", 0, l.size());
+        assertEquals(0, l.size(), "Validation of the letter 'A'.");
 
-      l.clear();
-      bean.setLetter("AA");
+        l.clear();
+        bean.setLetter("AA");
 
-      try {
-         validator.validate();
-      } catch (final Exception e) {
-         fail("An exception was thrown while calling Validator.validate()");
-      }
+        try {
+            validator.validate();
+        } catch (final Exception e) {
+            fail("An exception was thrown while calling Validator.validate()");
+        }
 
-      assertEquals("Validation of the letter 'AA'.", 1, l.size());
-   }
+        assertEquals(1, l.size(), "Validation of the letter 'AA'.");
+    }
 
-   /**
-    * Checks if the field is one upper case letter between 'A' and 'Z'.
-    */
-   public static boolean isCapLetter(final Object bean, final Field field, final List<String> l) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
+    /**
+     * Verify that one value generates an error and the other passes. The validation method being tested returns a <code>boolean</code> value.
+     */
+    @Test
+    public void testManualBooleanDeprecated() {
+        final ValidatorResources resources = new ValidatorResources();
 
-      if ((value == null) || (value.length() != 1)) {
-         l.add("Error");
-         return false;
-      }
-    if (value.charAt(0) >= 'A' && value.charAt(0) <= 'Z') {
-        return true;
-     }
-    l.add("Error");
-    return false;
-   }
+        final ValidatorAction va = new ValidatorAction();
+        va.setName("capLetter");
+        va.setClassname("org.apache.commons.validator.ValidatorTest");
+        va.setMethod("isCapLetter");
+        va.setMethodParams("java.lang.Object,org.apache.commons.validator.Field,java.util.List");
 
-   /**
-    * Formats a <code>String</code> to a <code>Date</code>.
-    * The <code>Validator</code> will interpret a <code>null</code>
-    * as validation having failed.
-    */
-   public static Date formatDate(final Object bean, final Field field) {
-      final String value = ValidatorUtils.getValueAsString(bean, field.getProperty());
-      Date date = null;
+        final FormSet fs = new FormSet();
+        final Form form = new Form();
+        form.setName("testForm");
+        final Field field = new Field();
+        field.setProperty("letter");
+        field.setDepends("capLetter");
+        form.addField(field);
+        fs.addForm(form);
 
-      try {
-          final DateFormat formatter = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US);
+        resources.addValidatorAction(va);
+        resources.addFormSet(fs);
+        resources.process();
 
-         formatter.setLenient(false);
+        final List<?> l = new ArrayList<>();
 
-         date = formatter.parse(value);
-      } catch (final ParseException e) {
-         System.out.println("ValidatorTest.formatDate() - " + e.getMessage());
-      }
+        final TestBean bean = new TestBean();
+        bean.setLetter("A");
 
-      return date;
-   }
+        final Validator validator = new Validator(resources, "testForm");
+        validator.setParameter(Validator.BEAN_PARAM, bean);
+        validator.setParameter("java.util.List", l);
 
-   public static class TestBean {
-      private String letter;
-      private String date;
+        try {
+            validator.validate();
+        } catch (final Exception e) {
+            fail("An exception was thrown while calling Validator.validate()");
+        }
 
-      public String getLetter() {
-         return letter;
-      }
+        assertEquals(0, l.size(), "Validation of the letter 'A'.");
 
-      public void setLetter(final String letter) {
-         this.letter = letter;
-      }
+        l.clear();
+        bean.setLetter("AA");
 
-      public String getDate() {
-         return date;
-      }
+        try {
+            validator.validate();
+        } catch (final Exception e) {
+            fail("An exception was thrown while calling Validator.validate()");
+        }
 
-      public void setDate(final String date) {
-         this.date = date;
-      }
-   }
+        assertEquals(1, l.size(), "Validation of the letter 'AA'.");
+    }
+
+    /**
+     * Verify that one value generates an error and the other passes. The validation method being tested returns an object ({@code null} will be considered
+     * an error).
+     */
+    @Test
+    public void testManualObject() {
+        // property name of the method we are validating
+        final String property = "date";
+        // name of ValidatorAction
+        final String action = "date";
+        final ValidatorResources resources = setupDateResources(property, action);
+
+        final TestBean bean = new TestBean();
+        bean.setDate("2/3/1999");
+
+        final Validator validator = new Validator(resources, "testForm");
+        validator.setParameter(Validator.BEAN_PARAM, bean);
+
+        try {
+            final ValidatorResults results = validator.validate();
+
+            assertNotNull(results, "Results are null.");
+
+            final ValidatorResult result = results.getValidatorResult(property);
+
+            assertNotNull(results, "Results are null.");
+
+            assertTrue(result.containsAction(action), "ValidatorResult does not contain '" + action + "' validator result.");
+
+            assertTrue(result.isValid(action), "Validation of the date formatting has failed.");
+        } catch (final Exception e) {
+            fail("An exception was thrown while calling Validator.validate()");
+        }
+
+        bean.setDate("2/30/1999");
+
+        try {
+            final ValidatorResults results = validator.validate();
+
+            assertNotNull(results, "Results are null.");
+
+            final ValidatorResult result = results.getValidatorResult(property);
+
+            assertNotNull(results, "Results are null.");
+
+            assertTrue(result.containsAction(action), "ValidatorResult does not contain '" + action + "' validator result.");
+
+            assertTrue(!result.isValid(action), "Validation of the date formatting has passed when it should have failed.");
+        } catch (final Exception e) {
+            fail("An exception was thrown while calling Validator.validate()");
+        }
+
+    }
+
+    @Test
+    public void testOnlyReturnErrors() throws ValidatorException {
+        // property name of the method we are validating
+        final String property = "date";
+        // name of ValidatorAction
+        final String action = "date";
+        final ValidatorResources resources = setupDateResources(property, action);
+
+        final TestBean bean = new TestBean();
+        bean.setDate("2/3/1999");
+
+        final Validator validator = new Validator(resources, "testForm");
+        validator.setParameter(Validator.BEAN_PARAM, bean);
+
+        ValidatorResults results = validator.validate();
+
+        assertNotNull(results);
+
+        // Field passed and should be in results
+        assertTrue(results.getPropertyNames().contains(property));
+
+        // Field passed but should not be in results
+        validator.setOnlyReturnErrors(true);
+        results = validator.validate();
+        assertFalse(results.getPropertyNames().contains(property));
+    }
+
+    @Test
+    public void testOnlyValidateField() throws ValidatorException {
+        // property name of the method we are validating
+        final String property = "date";
+        // name of ValidatorAction
+        final String action = "date";
+        final ValidatorResources resources = setupDateResources(property, action);
+
+        final TestBean bean = new TestBean();
+        bean.setDate("2/3/1999");
+
+        final Validator validator = new Validator(resources, "testForm", property);
+        validator.setParameter(Validator.BEAN_PARAM, bean);
+
+        final ValidatorResults results = validator.validate();
+
+        assertNotNull(results);
+
+        // Field passed and should be in results
+        assertTrue(results.getPropertyNames().contains(property));
+    }
 
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/ValueBean.java b/src/test/java/org/apache/commons/validator/ValueBean.java
index 54a34bc..c84a2fc 100644
--- a/src/test/java/org/apache/commons/validator/ValueBean.java
+++ b/src/test/java/org/apache/commons/validator/ValueBean.java
@@ -21,20 +21,20 @@
  */
 public class ValueBean {
 
-   protected String value;
+    protected String value;
 
-   /**
-    * Gets the value.
-    */
-   public String getValue() {
-      return value;
-   }
+    /**
+     * Gets the value.
+     */
+    public String getValue() {
+        return value;
+    }
 
-   /**
-    * Sets the value.
-    */
-   public void setValue(final String value) {
-      this.value = value;
-   }
+    /**
+     * Sets the value.
+     */
+    public void setValue(final String value) {
+        this.value = value;
+    }
 
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/VarTest.java b/src/test/java/org/apache/commons/validator/VarTest.java
index 362c2d8..85e50f6 100644
--- a/src/test/java/org/apache/commons/validator/VarTest.java
+++ b/src/test/java/org/apache/commons/validator/VarTest.java
@@ -16,92 +16,93 @@
  */
 package org.apache.commons.validator;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.IOException;
 import java.util.Locale;
 
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 import org.xml.sax.SAXException;
 
 /**
- * Test that the new Var attributes and the
- * digester rule changes work.
+ * Test that the new Var attributes and the digester rule changes work.
  */
 public class VarTest extends AbstractCommonTest {
 
-   /**
-    * The key used to retrieve the set of validation
-    * rules from the xml file.
-    */
-   protected static String FORM_KEY = "testForm";
+    /**
+     * The key used to retrieve the set of validation rules from the xml file.
+     */
+    protected static String FORM_KEY = "testForm";
 
-   /**
-    * The key used to retrieve the validator action.
-    */
-   protected static String ACTION = "byte";
+    /**
+     * The key used to retrieve the validator action.
+     */
+    protected static String ACTION = "byte";
 
+    /**
+     * Load <code>ValidatorResources</code> from validator-multipletest.xml.
+     */
+    @BeforeEach
+    protected void setUp() throws IOException, SAXException {
+        // Load resources
+        loadResources("VarTest-config.xml");
+    }
 
+    @AfterEach
+    protected void tearDown() {
+    }
 
-   public VarTest(final String name) {
-       super(name);
-   }
+    /**
+     * With nothing provided, we should fail both because both are required.
+     */
+    @Test
+    public void testVars() {
 
-   /**
-    * Load <code>ValidatorResources</code> from
-    * validator-multipletest.xml.
-    */
-   @Override
-protected void setUp() throws IOException, SAXException {
-      // Load resources
-      loadResources("VarTest-config.xml");
-   }
+        final Form form = resources.getForm(Locale.getDefault(), FORM_KEY);
 
-   @Override
-protected void tearDown() {
-   }
+        // Get field 1
+        final Field field1 = form.getField("field-1");
+        assertNotNull(field1, "field-1 is null.");
+        assertEquals(field1.getProperty(), "field-1", "field-1 property is wrong");
 
-   /**
-    * With nothing provided, we should fail both because both are required.
-    */
-   public void testVars() {
+        // Get var-1-1
+        final Var var11 = field1.getVar("var-1-1");
+        assertNotNull(var11, "var-1-1 is null.");
+        assertEquals(var11.getName(), "var-1-1", "var-1-1 name is wrong");
+        assertEquals(var11.getValue(), "value-1-1", "var-1-1 value is wrong");
+        assertEquals(var11.getJsType(), "jstype-1-1", "var-1-1 jstype is wrong");
+        assertFalse(var11.isResource(), "var-1-1 resource is true");
+        assertNull(var11.getBundle(), "var-1-1 bundle is not null.");
 
-       final Form form = resources.getForm(Locale.getDefault(), FORM_KEY);
+        // Get field 2
+        final Field field2 = form.getField("field-2");
+        assertNotNull(field2, "field-2 is null.");
+        assertEquals(field2.getProperty(), "field-2", "field-2 property is wrong");
 
-       // Get field 1
-       final Field field1 = form.getField("field-1");
-       assertNotNull("field-1 is null.", field1);
-       assertEquals("field-1 property is wrong", "field-1", field1.getProperty());
+        // Get var-2-1
+        final Var var21 = field2.getVar("var-2-1");
+        assertNotNull(var21, "var-2-1 is null.");
+        assertEquals(var21.getName(), "var-2-1", "var-2-1 name is wrong");
+        assertEquals(var21.getValue(), "value-2-1", "var-2-1 value is wrong");
+        assertEquals("jstype-2-1", var21.getJsType(), "var-2-1 jstype is wrong");
+        assertTrue(var21.isResource(), "var-2-1 resource is false");
+        assertEquals(var21.getBundle(), "bundle-2-1", "var-2-1 bundle is wrong");
 
-       // Get var-1-1
-       final Var var11 = field1.getVar("var-1-1");
-       assertNotNull("var-1-1 is null.", var11);
-       assertEquals("var-1-1 name is wrong", "var-1-1", var11.getName());
-       assertEquals("var-1-1 value is wrong", "value-1-1", var11.getValue());
-       assertEquals("var-1-1 jstype is wrong", "jstype-1-1", var11.getJsType());
-       assertFalse("var-1-1 resource is true", var11.isResource());
-       assertNull("var-1-1 bundle is not null.", var11.getBundle());
+        // Get var-2-2
+        final Var var22 = field2.getVar("var-2-2");
+        assertNotNull(var22, "var-2-2 is null.");
+        assertEquals(var22.getName(), "var-2-2", "var-2-2 name is wrong");
+        assertEquals(var22.getValue(), "value-2-2", "var-2-2 value is wrong");
+        assertNull(var22.getJsType(), "var-2-2 jstype is not null");
+        assertFalse(var22.isResource(), "var-2-2 resource is true");
+        assertEquals(var22.getBundle(), "bundle-2-2", "var-2-2 bundle is wrong");
 
-       // Get field 2
-       final Field field2 = form.getField("field-2");
-       assertNotNull("field-2 is null.", field2);
-       assertEquals("field-2 property is wrong", "field-2", field2.getProperty());
-
-       // Get var-2-1
-       final Var var21 = field2.getVar("var-2-1");
-       assertNotNull("var-2-1 is null.", var21);
-       assertEquals("var-2-1 name is wrong", "var-2-1", var21.getName());
-       assertEquals("var-2-1 value is wrong", "value-2-1", var21.getValue());
-       assertEquals("var-2-1 jstype is wrong", "jstype-2-1", var21.getJsType());
-       assertTrue("var-2-1 resource is false", var21.isResource());
-       assertEquals("var-2-1 bundle is wrong", "bundle-2-1", var21.getBundle());
-
-       // Get var-2-2
-       final Var var22 = field2.getVar("var-2-2");
-       assertNotNull("var-2-2 is null.", var22);
-       assertEquals("var-2-2 name is wrong", "var-2-2", var22.getName());
-       assertEquals("var-2-2 value is wrong", "value-2-2", var22.getValue());
-       assertNull("var-2-2 jstype is not null", var22.getJsType());
-       assertFalse("var-2-2 resource is true", var22.isResource());
-       assertEquals("var-2-2 bundle is wrong", "bundle-2-2", var22.getBundle());
-
-   }
+    }
 
 }
\ No newline at end of file
diff --git a/src/test/java/org/apache/commons/validator/routines/AbstractCalendarValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/AbstractCalendarValidatorTest.java
index 606f5dd..33ca4a0 100644
--- a/src/test/java/org/apache/commons/validator/routines/AbstractCalendarValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/AbstractCalendarValidatorTest.java
@@ -16,6 +16,13 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.ObjectInputStream;
@@ -25,197 +32,20 @@
 import java.util.Locale;
 import java.util.TimeZone;
 
-import junit.framework.TestCase;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * Base Calendar Test Case.
  */
-public abstract class AbstractCalendarValidatorTest extends TestCase {
-
-    protected AbstractCalendarValidator validator;
+public abstract class AbstractCalendarValidatorTest {
 
     protected static final TimeZone GMT = TimeZone.getTimeZone("GMT"); // 0 offset
+
     protected static final TimeZone EST = TimeZone.getTimeZone("EST"); // - 5 hours
     protected static final TimeZone EET = TimeZone.getTimeZone("EET"); // + 2 hours
     protected static final TimeZone UTC = TimeZone.getTimeZone("UTC"); // + 2 hours
 
-    protected String[] patternValid = {
-                       "2005-01-01"
-                      ,"2005-12-31"
-                      ,"2004-02-29"    // valid leap
-                      ,"2005-04-30"
-                      ,"05-12-31"
-                      ,"2005-1-1"
-                      ,"05-1-1"};
-    protected String[] localeValid = {
-                       "01/01/2005"
-                      ,"12/31/2005"
-                      ,"02/29/2004"    // valid leap
-                      ,"04/30/2005"
-                      ,"12/31/05"
-                      ,"1/1/2005"
-                      ,"1/1/05"};
-    protected Date[] patternExpect = {
-                      createDate(null, 20050101, 0)
-                     ,createDate(null, 20051231, 0)
-                     ,createDate(null, 20040229, 0)
-                     ,createDate(null, 20050430, 0)
-                     ,createDate(null, 20051231, 0)
-                     ,createDate(null, 20050101, 0)
-                     ,createDate(null, 20050101, 0)};
-    protected String[] patternInvalid = {
-                         "2005-00-01"  // zero month
-                        ,"2005-01-00"  // zero day
-                        ,"2005-13-03"  // month invalid
-                        ,"2005-04-31"  // invalid day
-                        ,"2005-03-32"  // invalid day
-                        ,"2005-02-29"  // invalid leap
-                        ,"200X-01-01"  // invalid char
-                        ,"2005-0X-01"  // invalid char
-                        ,"2005-01-0X"  // invalid char
-                        ,"01/01/2005"  // invalid pattern
-                        ,"2005-01"     // invalid pattern
-                        ,"2005--01"    // invalid pattern
-                        ,"2005-01-"};  // invalid pattern
-    protected String[] localeInvalid = {
-                         "01/00/2005"  // zero month
-                        ,"00/01/2005"  // zero day
-                        ,"13/01/2005"  // month invalid
-                        ,"04/31/2005"  // invalid day
-                        ,"03/32/2005"  // invalid day
-                        ,"02/29/2005"  // invalid leap
-                        ,"01/01/200X"  // invalid char
-                        ,"01/0X/2005"  // invalid char
-                        ,"0X/01/2005"  // invalid char
-                        ,"01-01-2005"  // invalid pattern
-                        ,"01/2005"     // invalid pattern
-       // --------      ,"/01/2005"    ---- passes on some JDK
-                        ,"01//2005"};  // invalid pattern
-
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public AbstractCalendarValidatorTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set Up.
-     * @throws Exception
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
-
-    /**
-     * Tear down
-     * @throws Exception
-     */
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-        validator = null;
-    }
-
-    /**
-     * Test Valid Dates with "pattern" validation
-     */
-    public void testPatternValid() {
-        for (int i = 0; i < patternValid.length; i++) {
-            final String text = i + " value=[" +patternValid[i]+"] failed ";
-            Object date = validator.parse(patternValid[i], "yy-MM-dd", null, null);
-            assertNotNull("validateObj() " + text + date,  date);
-            assertTrue("isValid() " + text,  validator.isValid(patternValid[i], "yy-MM-dd"));
-            if (date instanceof Calendar) {
-                date = ((Calendar)date).getTime();
-            }
-            assertEquals("compare " + text, patternExpect[i], date);
-        }
-    }
-
-    /**
-     * Test Invalid Dates with "pattern" validation
-     */
-    public void testPatternInvalid() {
-        for (int i = 0; i < patternInvalid.length; i++) {
-            final String text = i + " value=[" +patternInvalid[i]+"] passed ";
-            final Object date = validator.parse(patternInvalid[i], "yy-MM-dd", null, null);
-            assertNull("validateObj() " + text + date,  date);
-            assertFalse("isValid() " + text,  validator.isValid(patternInvalid[i], "yy-MM-dd"));
-        }
-    }
-
-    /**
-     * Test Valid Dates with "locale" validation
-     */
-    public void testLocaleValid() {
-        for (int i = 0; i < localeValid.length; i++) {
-            final String text = i + " value=[" +localeValid[i]+"] failed ";
-            Object date = validator.parse(localeValid[i], null, Locale.US, null);
-            assertNotNull("validateObj() " + text + date,  date);
-            assertTrue("isValid() " + text,  validator.isValid(localeValid[i], Locale.US));
-            if (date instanceof Calendar) {
-                date = ((Calendar)date).getTime();
-            }
-            assertEquals("compare " + text, patternExpect[i], date);
-        }
-    }
-
-    /**
-     * Test Invalid Dates with "locale" validation
-     */
-    public void testLocaleInvalid() {
-        for (int i = 0; i < localeInvalid.length; i++) {
-            final String text = i + " value=[" +localeInvalid[i]+"] passed ";
-            final Object date = validator.parse(localeInvalid[i], null, Locale.US, null);
-            assertNull("validateObj() " + text + date,  date);
-            assertFalse("isValid() " + text,  validator.isValid(localeInvalid[i], Locale.US));
-        }
-    }
-
-    /**
-     * Test Invalid Dates with "locale" validation
-     */
-    public void testFormat() {
-
-        // Create a Date or Calendar
-        final Object test = validator.parse("2005-11-28", "yyyy-MM-dd", null, null);
-        assertNotNull("Test Date ", test);
-        assertEquals("Format pattern", "28.11.05", validator.format(test, "dd.MM.yy"));
-        assertEquals("Format locale",  "11/28/05", validator.format(test, Locale.US));
-    }
-
-    /**
-     * Test validator serialization.
-     */
-    public void testSerialization() {
-        // Serialize the check digit routine
-        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        try {
-            final ObjectOutputStream oos = new ObjectOutputStream(baos);
-            oos.writeObject(validator);
-            oos.flush();
-            oos.close();
-        } catch (final Exception e) {
-            fail(validator.getClass().getName() + " error during serialization: " + e);
-        }
-
-        // Deserialize the test object
-        Object result = null;
-        try {
-            final ByteArrayInputStream bais =
-                new ByteArrayInputStream(baos.toByteArray());
-            final ObjectInputStream ois = new ObjectInputStream(bais);
-            result = ois.readObject();
-            bais.close();
-        } catch (final Exception e) {
-            fail(validator.getClass().getName() + " error during deserialization: " + e);
-        }
-        assertNotNull(result);
-    }
-
     /**
      * Create a calendar instance for a specified time zone, date and time.
      *
@@ -225,21 +55,20 @@
      * @return the new Calendar instance.
      */
     protected static Calendar createCalendar(final TimeZone zone, final int date, final int time) {
-        final Calendar calendar = zone == null ? Calendar.getInstance()
-                                         : Calendar.getInstance(zone);
-        final int year = ((date / 10000) * 10000);
-        final int mth  = ((date / 100) * 100) - year;
+        final Calendar calendar = zone == null ? Calendar.getInstance() : Calendar.getInstance(zone);
+        final int year = date / 10000 * 10000;
+        final int mth = date / 100 * 100 - year;
         final int day = date - (year + mth);
-        final int hour = ((time / 10000) * 10000);
-        final int min  = ((time / 100) * 100) - hour;
-        final int sec  = time - (hour + min);
-        calendar.set(Calendar.YEAR,  (year / 10000));
-        calendar.set(Calendar.MONTH, ((mth / 100) - 1));
-        calendar.set(Calendar.DATE,  day);
-        calendar.set(Calendar.HOUR_OF_DAY,  (hour / 10000));
-        calendar.set(Calendar.MINUTE, (min / 100));
-        calendar.set(Calendar.SECOND,  sec);
-        calendar.set(Calendar.MILLISECOND,  0);
+        final int hour = time / 10000 * 10000;
+        final int min = time / 100 * 100 - hour;
+        final int sec = time - (hour + min);
+        calendar.set(Calendar.YEAR, year / 10000);
+        calendar.set(Calendar.MONTH, mth / 100 - 1);
+        calendar.set(Calendar.DATE, day);
+        calendar.set(Calendar.HOUR_OF_DAY, hour / 10000);
+        calendar.set(Calendar.MINUTE, min / 100);
+        calendar.set(Calendar.SECOND, sec);
+        calendar.set(Calendar.MILLISECOND, 0);
         return calendar;
     }
 
@@ -256,4 +85,146 @@
         return calendar.getTime();
     }
 
+    protected AbstractCalendarValidator validator;
+    protected String[] patternValid = { "2005-01-01", "2005-12-31", "2004-02-29" // valid leap
+            , "2005-04-30", "05-12-31", "2005-1-1", "05-1-1" };
+    protected String[] localeValid = { "01/01/2005", "12/31/2005", "02/29/2004" // valid leap
+            , "04/30/2005", "12/31/05", "1/1/2005", "1/1/05" };
+    protected Date[] patternExpect = { createDate(null, 20050101, 0), createDate(null, 20051231, 0), createDate(null, 20040229, 0),
+            createDate(null, 20050430, 0), createDate(null, 20051231, 0), createDate(null, 20050101, 0), createDate(null, 20050101, 0) };
+
+    protected String[] patternInvalid = { "2005-00-01" // zero month
+            , "2005-01-00" // zero day
+            , "2005-13-03" // month invalid
+            , "2005-04-31" // invalid day
+            , "2005-03-32" // invalid day
+            , "2005-02-29" // invalid leap
+            , "200X-01-01" // invalid char
+            , "2005-0X-01" // invalid char
+            , "2005-01-0X" // invalid char
+            , "01/01/2005" // invalid pattern
+            , "2005-01" // invalid pattern
+            , "2005--01" // invalid pattern
+            , "2005-01-" }; // invalid pattern
+
+    protected String[] localeInvalid = { "01/00/2005" // zero month
+            , "00/01/2005" // zero day
+            , "13/01/2005" // month invalid
+            , "04/31/2005" // invalid day
+            , "03/32/2005" // invalid day
+            , "02/29/2005" // invalid leap
+            , "01/01/200X" // invalid char
+            , "01/0X/2005" // invalid char
+            , "0X/01/2005" // invalid char
+            , "01-01-2005" // invalid pattern
+            , "01/2005" // invalid pattern
+            // -------- ,"/01/2005" ---- passes on some JDK
+            , "01//2005" }; // invalid pattern
+
+    /**
+     * Tear down
+     */
+    @AfterEach
+    protected void tearDown() {
+        validator = null;
+    }
+
+    /**
+     * Test Invalid Dates with "locale" validation
+     */
+    @Test
+    public void testFormat() {
+
+        // Create a Date or Calendar
+        final Object test = validator.parse("2005-11-28", "yyyy-MM-dd", null, null);
+        assertNotNull(test, "Test Date");
+        assertEquals("28.11.05", validator.format(test, "dd.MM.yy"), "Format pattern");
+        assertEquals("11/28/05", validator.format(test, Locale.US), "Format locale");
+    }
+
+    /**
+     * Test Invalid Dates with "locale" validation
+     */
+    @Test
+    public void testLocaleInvalid() {
+        for (int i = 0; i < localeInvalid.length; i++) {
+            final String text = i + " value=[" + localeInvalid[i] + "] passed ";
+            final Object date = validator.parse(localeInvalid[i], null, Locale.US, null);
+            assertNull(date, "validateObj() " + text + date);
+            assertFalse(validator.isValid(localeInvalid[i], Locale.US), "isValid() " + text);
+        }
+    }
+
+    /**
+     * Test Valid Dates with "locale" validation
+     */
+    @Test
+    public void testLocaleValid() {
+        for (int i = 0; i < localeValid.length; i++) {
+            final String text = i + " value=[" + localeValid[i] + "] failed ";
+            Object date = validator.parse(localeValid[i], null, Locale.US, null);
+            assertNotNull(date, "validateObj() " + text + date);
+            assertTrue(validator.isValid(localeValid[i], Locale.US), "isValid() " + text);
+            if (date instanceof Calendar) {
+                date = ((Calendar) date).getTime();
+            }
+            assertEquals(patternExpect[i], date, "compare " + text);
+        }
+    }
+
+    /**
+     * Test Invalid Dates with "pattern" validation
+     */
+    @Test
+    public void testPatternInvalid() {
+        for (int i = 0; i < patternInvalid.length; i++) {
+            final String text = i + " value=[" + patternInvalid[i] + "] passed ";
+            final Object date = validator.parse(patternInvalid[i], "yy-MM-dd", null, null);
+            assertNull(date, "validateObj() " + text + date);
+            assertFalse(validator.isValid(patternInvalid[i], "yy-MM-dd"), "isValid() " + text);
+        }
+    }
+
+    /**
+     * Test Valid Dates with "pattern" validation
+     */
+    @Test
+    public void testPatternValid() {
+        for (int i = 0; i < patternValid.length; i++) {
+            final String text = i + " value=[" + patternValid[i] + "] failed ";
+            Object date = validator.parse(patternValid[i], "yy-MM-dd", null, null);
+            assertNotNull(date, "validateObj() " + text + date);
+            assertTrue(validator.isValid(patternValid[i], "yy-MM-dd"), "isValid() " + text);
+            if (date instanceof Calendar) {
+                date = ((Calendar) date).getTime();
+            }
+            assertEquals(patternExpect[i], date, "compare " + text);
+        }
+    }
+
+    /**
+     * Test validator serialization.
+     */
+    @Test
+    public void testSerialization() {
+        // Serialize the check digit routine
+        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
+            oos.writeObject(validator);
+            oos.flush();
+        } catch (final Exception e) {
+            fail(validator.getClass().getName() + " error during serialization: " + e);
+        }
+
+        // Deserialize the test object
+        Object result = null;
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray())) {
+            final ObjectInputStream ois = new ObjectInputStream(bais);
+            result = ois.readObject();
+        } catch (final Exception e) {
+            fail(validator.getClass().getName() + " error during deserialization: " + e);
+        }
+        assertNotNull(result);
+    }
+
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/AbstractNumberValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/AbstractNumberValidatorTest.java
index a484eb9..a9847cf 100644
--- a/src/test/java/org/apache/commons/validator/routines/AbstractNumberValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/AbstractNumberValidatorTest.java
@@ -16,6 +16,13 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.ObjectInputStream;
@@ -24,11 +31,14 @@
 import java.text.DecimalFormat;
 import java.util.Locale;
 
-import junit.framework.TestCase;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Base Number Test Case.
  */
-public abstract class AbstractNumberValidatorTest extends TestCase {
+public abstract class AbstractNumberValidatorTest {
 
     protected AbstractNumberValidator validator;
     protected AbstractNumberValidator strictValidator;
@@ -56,136 +66,72 @@
     protected Locale testLocale;
     protected Number localeExpected;
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public AbstractNumberValidatorTest(final String name) {
-        super(name);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
+    @BeforeEach
+    protected void setUp() {
         Locale.setDefault(Locale.US);
-
     }
 
     /**
      * Tear down
-     * @throws Exception
      */
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
+    @AfterEach
+    protected void tearDown() {
         validator = null;
         strictValidator = null;
     }
 
     /**
-     * Test Format Type
+     * Test format() methods
      */
-    public void testFormatType() {
-        assertEquals("Format Type A", 0, validator.getFormatType());
-        assertEquals("Format Type B", AbstractNumberValidator.STANDARD_FORMAT, validator.getFormatType());
+    @Test
+    public void testFormat() {
+        final Number number = new BigDecimal("1234.5");
+        assertEquals("1,234.5", strictValidator.format(number, Locale.US), "US Locale, US Format");
+        assertEquals("1.234,5", strictValidator.format(number, Locale.GERMAN), "DE Locale, DE Format");
+        assertEquals("12,34.50", strictValidator.format(number, "#,#0.00"), "Pattern #,#0.00");
     }
 
     /**
-     * Test Min/Max values allowed
+     * Test Format Type
      */
-    public void testValidateMinMax() {
-        final DecimalFormat fmt = new DecimalFormat("#");
-        if (max != null) {
-            assertEquals("Test Max",   max, validator.parse(fmt.format(max), "#", null));
-            assertNull("Test Max + 1",      validator.parse(fmt.format(maxPlusOne), "#", null));
-            assertEquals("Test Min",   min, validator.parse(fmt.format(min), "#", null));
-            assertNull("Test min - 1",      validator.parse(fmt.format(minMinusOne), "#", null));
+    @Test
+    public void testFormatType() {
+        assertEquals(0, validator.getFormatType(), "Format Type A");
+        assertEquals(AbstractNumberValidator.STANDARD_FORMAT, validator.getFormatType(), "Format Type B");
+    }
+
+    /**
+     * Test Invalid, strict=false
+     */
+    @Test
+    public void testInvalidNotStrict() {
+        for (int i = 0; i < invalid.length; i++) {
+            final String text = "idx=[" + i + "] value=[" + invalid[i] + "]";
+            assertNull(validator.parse(invalid[i], null, Locale.US), () -> "(A) " + text);
+            assertFalse(validator.isValid(invalid[i], null, Locale.US), () -> "(B) " + text);
+            assertNull(validator.parse(invalid[i], testPattern, null), () -> "(C) " + text);
+            assertFalse(validator.isValid(invalid[i], testPattern, null), () -> "(D) " + text);
         }
     }
 
     /**
      * Test Invalid, strict=true
      */
+    @Test
     public void testInvalidStrict() {
         for (int i = 0; i < invalidStrict.length; i++) {
-            final String text = "idx=["+i+"] value=[" + invalidStrict[i] + "]";
-            assertNull("(A) "  + text, strictValidator.parse(invalidStrict[i], null, Locale.US));
-            assertFalse("(B) " + text, strictValidator.isValid(invalidStrict[i], null, Locale.US));
-            assertNull("(C) "  + text, strictValidator.parse(invalidStrict[i], testPattern, null));
-            assertFalse("(D) " + text, strictValidator.isValid(invalidStrict[i], testPattern, null));
+            final String text = "idx=[" + i + "] value=[" + invalidStrict[i] + "]";
+            assertNull(strictValidator.parse(invalidStrict[i], null, Locale.US), () -> "(A) " + text);
+            assertFalse(strictValidator.isValid(invalidStrict[i], null, Locale.US), () -> "(B) " + text);
+            assertNull(strictValidator.parse(invalidStrict[i], testPattern, null), () -> "(C) " + text);
+            assertFalse(strictValidator.isValid(invalidStrict[i], testPattern, null), () -> "(D) " + text);
         }
     }
 
     /**
-     * Test Invalid, strict=false
-     */
-    public void testInvalidNotStrict() {
-        for (int i = 0; i < invalid.length; i++) {
-            final String text = "idx=["+i+"] value=[" + invalid[i] + "]";
-            assertNull("(A) "  + text, validator.parse(invalid[i], null, Locale.US));
-            assertFalse("(B) " + text, validator.isValid(invalid[i], null, Locale.US));
-            assertNull("(C) "  + text, validator.parse(invalid[i], testPattern, null));
-            assertFalse("(D) " + text, validator.isValid(invalid[i], testPattern, null));
-        }
-    }
-
-    /**
-     * Test Valid, strict=true
-     */
-    public void testValidStrict() {
-        for (int i = 0; i < validStrict.length; i++) {
-            final String text = "idx=["+i+"] value=[" + validStrictCompare[i] + "]";
-            assertEquals("(A) "  + text, validStrictCompare[i], strictValidator.parse(validStrict[i], null, Locale.US));
-            assertTrue("(B) "    + text,                        strictValidator.isValid(validStrict[i], null, Locale.US));
-            assertEquals("(C) "  + text, validStrictCompare[i], strictValidator.parse(validStrict[i], testPattern, null));
-            assertTrue("(D) "    + text,                        strictValidator.isValid(validStrict[i], testPattern, null));
-        }
-    }
-
-    /**
-     * Test Valid, strict=false
-     */
-    public void testValidNotStrict() {
-        for (int i = 0; i < valid.length; i++) {
-            final String text = "idx=["+i+"] value=[" + validCompare[i] + "]";
-            assertEquals("(A) "  + text, validCompare[i], validator.parse(valid[i], null, Locale.US));
-            assertTrue("(B) "    + text,                  validator.isValid(valid[i], null, Locale.US));
-            assertEquals("(C) "  + text, validCompare[i], validator.parse(valid[i], testPattern, null));
-            assertTrue("(D) "    + text,                  validator.isValid(valid[i], testPattern, null));
-        }
-    }
-
-    /**
-     * Test different Locale
-     */
-    public void testValidateLocale() {
-
-        assertEquals("US Locale, US Format", testNumber, strictValidator.parse(testStringUS, null, Locale.US));
-        assertNull("US Locale, DE Format", strictValidator.parse(testStringDE, null, Locale.US));
-
-        // Default German Locale
-        assertEquals("DE Locale, DE Format", testNumber, strictValidator.parse(testStringDE, null, Locale.GERMAN));
-        assertNull("DE Locale, US Format", strictValidator.parse(testStringUS, null, Locale.GERMAN));
-
-        // Default Locale has been set to Locale.US in setup()
-        assertEquals("Default Locale, US Format", testNumber, strictValidator.parse(testStringUS, null, null));
-        assertNull("Default Locale, DE Format", strictValidator.parse(testStringDE, null, null));
-    }
-
-    /**
-     * Test format() methods
-     */
-    public void testFormat() {
-        final Number number = new BigDecimal("1234.5");
-        assertEquals("US Locale, US Format", "1,234.5", strictValidator.format(number, Locale.US));
-        assertEquals("DE Locale, DE Format", "1.234,5", strictValidator.format(number, Locale.GERMAN));
-        assertEquals("Pattern #,#0.00", "12,34.50",  strictValidator.format(number, "#,#0.00"));
-    }
-
-    /**
      * Test Range/Min/Max
      */
+    @Test
     public void testRangeMinMax() {
         final Number number9 = Integer.valueOf(9);
         final Number number10 = Integer.valueOf(10);
@@ -195,50 +141,106 @@
         final Number number21 = Integer.valueOf(21);
 
         // Test isInRange()
-        assertFalse("isInRange() < min",   strictValidator.isInRange(number9 ,  number10, number20));
-        assertTrue("isInRange() = min",    strictValidator.isInRange(number10 , number10, number20));
-        assertTrue("isInRange() in range", strictValidator.isInRange(number11 , number10, number20));
-        assertTrue("isInRange() = max",    strictValidator.isInRange(number20 , number10, number20));
-        assertFalse("isInRange() > max",   strictValidator.isInRange(number21 , number10, number20));
+        assertFalse(strictValidator.isInRange(number9, number10, number20), "isInRange() < min");
+        assertTrue(strictValidator.isInRange(number10, number10, number20), "isInRange() = min");
+        assertTrue(strictValidator.isInRange(number11, number10, number20), "isInRange() in range");
+        assertTrue(strictValidator.isInRange(number20, number10, number20), "isInRange() = max");
+        assertFalse(strictValidator.isInRange(number21, number10, number20), "isInRange() > max");
 
         // Test minValue()
-        assertFalse("minValue() < min",    strictValidator.minValue(number9 ,  number10));
-        assertTrue("minValue() = min",     strictValidator.minValue(number10 , number10));
-        assertTrue("minValue() > min",     strictValidator.minValue(number11 , number10));
+        assertFalse(strictValidator.minValue(number9, number10), "minValue() < min");
+        assertTrue(strictValidator.minValue(number10, number10), "minValue() = min");
+        assertTrue(strictValidator.minValue(number11, number10), "minValue() > min");
 
         // Test minValue()
-        assertTrue("maxValue() < max",     strictValidator.maxValue(number19 , number20));
-        assertTrue("maxValue() = max",     strictValidator.maxValue(number20 , number20));
-        assertFalse("maxValue() > max",    strictValidator.maxValue(number21 , number20));
+        assertTrue(strictValidator.maxValue(number19, number20), "maxValue() < max");
+        assertTrue(strictValidator.maxValue(number20, number20), "maxValue() = max");
+        assertFalse(strictValidator.maxValue(number21, number20), "maxValue() > max");
     }
 
     /**
      * Test validator serialization.
      */
+    @Test
     public void testSerialization() {
         // Serialize the check digit routine
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        try {
-            final ObjectOutputStream oos = new ObjectOutputStream(baos);
+        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
             oos.writeObject(validator);
             oos.flush();
-            oos.close();
         } catch (final Exception e) {
             fail(validator.getClass().getName() + " error during serialization: " + e);
         }
 
         // Deserialize the test object
         Object result = null;
-        try {
-            final ByteArrayInputStream bais =
-                new ByteArrayInputStream(baos.toByteArray());
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray())) {
             final ObjectInputStream ois = new ObjectInputStream(bais);
             result = ois.readObject();
-            bais.close();
         } catch (final Exception e) {
             fail(validator.getClass().getName() + " error during deserialization: " + e);
         }
         assertNotNull(result);
     }
 
+    /**
+     * Test different Locale
+     */
+    @Test
+    public void testValidateLocale() {
+
+        assertEquals(testNumber, strictValidator.parse(testStringUS, null, Locale.US), "US Locale, US Format");
+        assertNull(strictValidator.parse(testStringDE, null, Locale.US), "US Locale, DE Format");
+
+        // Default German Locale
+        assertEquals(testNumber, strictValidator.parse(testStringDE, null, Locale.GERMAN), "DE Locale, DE Format");
+        assertNull(strictValidator.parse(testStringUS, null, Locale.GERMAN), "DE Locale, US Format");
+
+        // Default Locale has been set to Locale.US in setup()
+        assertEquals(testNumber, strictValidator.parse(testStringUS, null, null), "Default Locale, US Format");
+        assertNull(strictValidator.parse(testStringDE, null, null), "Default Locale, DE Format");
+    }
+
+    /**
+     * Test Min/Max values allowed
+     */
+    @Test
+    public void testValidateMinMax() {
+        final DecimalFormat fmt = new DecimalFormat("#");
+        if (max != null) {
+            assertEquals(max, validator.parse(fmt.format(max), "#", null), "Test Max");
+            assertNull(validator.parse(fmt.format(maxPlusOne), "#", null), "Test Max + 1");
+            assertEquals(min, validator.parse(fmt.format(min), "#", null), "Test Min");
+            assertNull(validator.parse(fmt.format(minMinusOne), "#", null), "Test min - 1");
+        }
+    }
+
+    /**
+     * Test Valid, strict=false
+     */
+    @Test
+    public void testValidNotStrict() {
+        for (int i = 0; i < valid.length; i++) {
+            final String text = "idx=[" + i + "] value=[" + validCompare[i] + "]";
+            assertEquals(validCompare[i], validator.parse(valid[i], null, Locale.US), "(A) " + text);
+            assertTrue(validator.isValid(valid[i], null, Locale.US), "(B) " + text);
+            assertEquals(validCompare[i], validator.parse(valid[i], testPattern, null), "(C) " + text);
+            assertTrue(validator.isValid(valid[i], testPattern, null), "(D) " + text);
+        }
+    }
+
+    /**
+     * Test Valid, strict=true
+     */
+    @Test
+    public void testValidStrict() {
+        for (int i = 0; i < validStrict.length; i++) {
+            final String text = "idx=[" + i + "] value=[" + validStrictCompare[i] + "]";
+            assertEquals(validStrictCompare[i], strictValidator.parse(validStrict[i], null, Locale.US), "(A) " + text);
+            assertTrue(strictValidator.isValid(validStrict[i], null, Locale.US), "(B) " + text);
+            assertEquals(validStrictCompare[i], strictValidator.parse(validStrict[i], testPattern, null), "(C) " + text);
+            assertTrue(strictValidator.isValid(validStrict[i], testPattern, null), "(D) " + text);
+        }
+    }
+
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/BigDecimalValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/BigDecimalValidatorTest.java
index 941efef..57a8150 100644
--- a/src/test/java/org/apache/commons/validator/routines/BigDecimalValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/BigDecimalValidatorTest.java
@@ -16,27 +16,28 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.math.BigDecimal;
 import java.util.Locale;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Test Case for BigDecimalValidator.
  */
 public class BigDecimalValidatorTest extends AbstractNumberValidatorTest {
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public BigDecimalValidatorTest(final String name) {
-        super(name);
-    }
-
     @Override
-    protected void setUp() throws Exception {
+    @BeforeEach
+    protected void setUp() {
         super.setUp();
 
-        validator       = new BigDecimalValidator(false);
+        validator = new BigDecimalValidator(false);
         strictValidator = new BigDecimalValidator();
 
         testPattern = "#,###.###";
@@ -48,20 +49,20 @@
         minMinusOne = null;
 
         // testInvalidStrict()
-        invalidStrict = new String[] {null, "", "X", "X12", "12X", "1X2", "1.234X"};
+        invalidStrict = new String[] { null, "", "X", "X12", "12X", "1X2", "1.234X" };
 
         // testInvalidNotStrict()
-        invalid       = new String[] {null, "", "X", "X12"};
+        invalid = new String[] { null, "", "X", "X12" };
 
         // testValid()
-        testNumber    = new BigDecimal("1234.5");
+        testNumber = new BigDecimal("1234.5");
         final Number testNumber2 = new BigDecimal(".1");
         final Number testNumber3 = new BigDecimal("12345.67899");
-        testZero      = new BigDecimal("0");
-        validStrict          = new String[] {"0", "1234.5", "1,234.5", ".1", "12345.678990"};
-        validStrictCompare   = new Number[] {testZero, testNumber, testNumber, testNumber2, testNumber3};
-        valid                = new String[] {"0", "1234.5", "1,234.5", "1,234.5", "1234.5X"};
-        validCompare         = new Number[] {testZero, testNumber, testNumber, testNumber, testNumber};
+        testZero = new BigDecimal("0");
+        validStrict = new String[] { "0", "1234.5", "1,234.5", ".1", "12345.678990" };
+        validStrictCompare = new Number[] { testZero, testNumber, testNumber, testNumber2, testNumber3 };
+        valid = new String[] { "0", "1234.5", "1,234.5", "1,234.5", "1234.5X" };
+        validCompare = new Number[] { testZero, testNumber, testNumber, testNumber, testNumber };
 
         testStringUS = "1,234.5";
         testStringDE = "1.234,5";
@@ -69,50 +70,18 @@
         // Localized Pattern test
         localeValue = testStringDE;
         localePattern = "#.###,#";
-        testLocale    = Locale.GERMANY;
+        testLocale = Locale.GERMANY;
         localeExpected = testNumber;
 
     }
 
     /**
-     * Test BigDecimalValidator validate Methods
-     */
-    public void testBigDecimalValidatorMethods() {
-        final Locale locale           = Locale.GERMAN;
-        final String pattern          = "0,00,00";
-        final String patternVal       = "1,23,45";
-        final String germanPatternVal = "1.23.45";
-        final String localeVal        = "12.345";
-        final String defaultVal       = "12,345";
-        final String XXXX             = "XXXX";
-        final BigDecimal expected = new BigDecimal(12345);
-        assertEquals("validate(A) default", expected, BigDecimalValidator.getInstance().validate(defaultVal));
-        assertEquals("validate(A) locale ", expected, BigDecimalValidator.getInstance().validate(localeVal, locale));
-        assertEquals("validate(A) pattern", expected, BigDecimalValidator.getInstance().validate(patternVal, pattern));
-        assertEquals("validate(A) both",    expected, BigDecimalValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertTrue("isValid(A) default", BigDecimalValidator.getInstance().isValid(defaultVal));
-        assertTrue("isValid(A) locale ", BigDecimalValidator.getInstance().isValid(localeVal, locale));
-        assertTrue("isValid(A) pattern", BigDecimalValidator.getInstance().isValid(patternVal, pattern));
-        assertTrue("isValid(A) both",    BigDecimalValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertNull("validate(B) default", BigDecimalValidator.getInstance().validate(XXXX));
-        assertNull("validate(B) locale ", BigDecimalValidator.getInstance().validate(XXXX, locale));
-        assertNull("validate(B) pattern", BigDecimalValidator.getInstance().validate(XXXX, pattern));
-        assertNull("validate(B) both",    BigDecimalValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN));
-
-        assertFalse("isValid(B) default", BigDecimalValidator.getInstance().isValid(XXXX));
-        assertFalse("isValid(B) locale ", BigDecimalValidator.getInstance().isValid(XXXX, locale));
-        assertFalse("isValid(B) pattern", BigDecimalValidator.getInstance().isValid(XXXX, pattern));
-        assertFalse("isValid(B) both",    BigDecimalValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN));
-    }
-
-    /**
      * Test BigDecimal Range/Min/Max
      */
+    @Test
     public void testBigDecimalRangeMinMax() {
         final BigDecimalValidator validator = new BigDecimalValidator(true, AbstractNumberValidator.STANDARD_FORMAT, true);
-        final BigDecimal number9  = new BigDecimal("9");
+        final BigDecimal number9 = new BigDecimal("9");
         final BigDecimal number10 = new BigDecimal("10");
         final BigDecimal number11 = new BigDecimal("11");
         final BigDecimal number19 = new BigDecimal("19");
@@ -123,20 +92,54 @@
         final float max = 20;
 
         // Test isInRange()
-        assertFalse("isInRange(A) < min",   validator.isInRange(number9,  min, max));
-        assertTrue("isInRange(A) = min",    validator.isInRange(number10, min, max));
-        assertTrue("isInRange(A) in range", validator.isInRange(number11, min, max));
-        assertTrue("isInRange(A) = max",    validator.isInRange(number20, min, max));
-        assertFalse("isInRange(A) > max",   validator.isInRange(number21, min, max));
+        assertFalse(validator.isInRange(number9, min, max), "isInRange(A) < min");
+        assertTrue(validator.isInRange(number10, min, max), "isInRange(A) = min");
+        assertTrue(validator.isInRange(number11, min, max), "isInRange(A) in range");
+        assertTrue(validator.isInRange(number20, min, max), "isInRange(A) = max");
+        assertFalse(validator.isInRange(number21, min, max), "isInRange(A) > max");
 
         // Test minValue()
-        assertFalse("minValue(A) < min",    validator.minValue(number9,  min));
-        assertTrue("minValue(A) = min",     validator.minValue(number10, min));
-        assertTrue("minValue(A) > min",     validator.minValue(number11, min));
+        assertFalse(validator.minValue(number9, min), "minValue(A) < min");
+        assertTrue(validator.minValue(number10, min), "minValue(A) = min");
+        assertTrue(validator.minValue(number11, min), "minValue(A) > min");
 
         // Test minValue()
-        assertTrue("maxValue(A) < max",     validator.maxValue(number19, max));
-        assertTrue("maxValue(A) = max",     validator.maxValue(number20, max));
-        assertFalse("maxValue(A) > max",    validator.maxValue(number21, max));
+        assertTrue(validator.maxValue(number19, max), "maxValue(A) < max");
+        assertTrue(validator.maxValue(number20, max), "maxValue(A) = max");
+        assertFalse(validator.maxValue(number21, max), "maxValue(A) > max");
+    }
+
+    /**
+     * Test BigDecimalValidator validate Methods
+     */
+    @Test
+    public void testBigDecimalValidatorMethods() {
+        final Locale locale = Locale.GERMAN;
+        final String pattern = "0,00,00";
+        final String patternVal = "1,23,45";
+        final String germanPatternVal = "1.23.45";
+        final String localeVal = "12.345";
+        final String defaultVal = "12,345";
+        final String XXXX = "XXXX";
+        final BigDecimal expected = new BigDecimal(12345);
+        assertEquals(expected, BigDecimalValidator.getInstance().validate(defaultVal), "validate(A) default");
+        assertEquals(expected, BigDecimalValidator.getInstance().validate(localeVal, locale), "validate(A) locale ");
+        assertEquals(expected, BigDecimalValidator.getInstance().validate(patternVal, pattern), "validate(A) pattern");
+        assertEquals(expected, BigDecimalValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN), "validate(A) both");
+
+        assertTrue(BigDecimalValidator.getInstance().isValid(defaultVal), "isValid(A) default");
+        assertTrue(BigDecimalValidator.getInstance().isValid(localeVal, locale), "isValid(A) locale ");
+        assertTrue(BigDecimalValidator.getInstance().isValid(patternVal, pattern), "isValid(A) pattern");
+        assertTrue(BigDecimalValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN), "isValid(A) both");
+
+        assertNull(BigDecimalValidator.getInstance().validate(XXXX), "validate(B) default");
+        assertNull(BigDecimalValidator.getInstance().validate(XXXX, locale), "validate(B) locale");
+        assertNull(BigDecimalValidator.getInstance().validate(XXXX, pattern), "validate(B) pattern");
+        assertNull(BigDecimalValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN), "validate(B) both");
+
+        assertFalse(BigDecimalValidator.getInstance().isValid(XXXX), "isValid(B) default");
+        assertFalse(BigDecimalValidator.getInstance().isValid(XXXX, locale), "isValid(B) locale");
+        assertFalse(BigDecimalValidator.getInstance().isValid(XXXX, pattern), "isValid(B) pattern");
+        assertFalse(BigDecimalValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN), "isValid(B) both");
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/BigIntegerValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/BigIntegerValidatorTest.java
index 1f5993d..549d896 100644
--- a/src/test/java/org/apache/commons/validator/routines/BigIntegerValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/BigIntegerValidatorTest.java
@@ -16,50 +16,51 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.math.BigInteger;
 import java.util.Locale;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Test Case for BigIntegerValidator.
  */
 public class BigIntegerValidatorTest extends AbstractNumberValidatorTest {
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public BigIntegerValidatorTest(final String name) {
-        super(name);
-    }
-
     @Override
-    protected void setUp() throws Exception {
+    @BeforeEach
+    protected void setUp() {
         super.setUp();
 
-        validator       = new BigIntegerValidator(false, 0);
+        validator = new BigIntegerValidator(false, 0);
         strictValidator = new BigIntegerValidator();
 
         testPattern = "#,###";
 
         // testValidateMinMax()
-        max =  null;
+        max = null;
         maxPlusOne = null;
         min = null;
         minMinusOne = null;
 
         // testInvalidStrict()
-        invalidStrict = new String[] {null, "", "X", "X12", "12X", "1X2", "1.2"};
+        invalidStrict = new String[] { null, "", "X", "X12", "12X", "1X2", "1.2" };
 
         // testInvalidNotStrict()
-        invalid       = new String[] {null, "", "X", "X12"};
+        invalid = new String[] { null, "", "X", "X12" };
 
         // testValid()
-        testNumber    = new BigInteger("1234");
-        testZero      = new BigInteger("0");
-        validStrict          = new String[] {"0", "1234", "1,234"};
-        validStrictCompare   = new Number[] {testZero, testNumber, testNumber};
-        valid                = new String[] {"0", "1234", "1,234", "1,234.5", "1234X"};
-        validCompare         = new Number[] {testZero, testNumber, testNumber, testNumber, testNumber};
+        testNumber = new BigInteger("1234");
+        testZero = new BigInteger("0");
+        validStrict = new String[] { "0", "1234", "1,234" };
+        validStrictCompare = new Number[] { testZero, testNumber, testNumber };
+        valid = new String[] { "0", "1234", "1,234", "1,234.5", "1234X" };
+        validCompare = new Number[] { testZero, testNumber, testNumber, testNumber, testNumber };
 
         testStringUS = "1,234";
         testStringDE = "1.234";
@@ -67,50 +68,18 @@
         // Localized Pattern test
         localeValue = testStringDE;
         localePattern = "#.###";
-        testLocale    = Locale.GERMANY;
+        testLocale = Locale.GERMANY;
         localeExpected = testNumber;
 
     }
 
     /**
-     * Test BigIntegerValidator validate Methods
-     */
-    public void testBigIntegerValidatorMethods() {
-        final Locale locale     = Locale.GERMAN;
-        final String pattern    = "0,00,00";
-        final String patternVal = "1,23,45";
-        final String germanPatternVal = "1.23.45";
-        final String localeVal  = "12.345";
-        final String defaultVal = "12,345";
-        final String XXXX    = "XXXX";
-        final BigInteger expected = new BigInteger("12345");
-        assertEquals("validate(A) default", expected, BigIntegerValidator.getInstance().validate(defaultVal));
-        assertEquals("validate(A) locale ", expected, BigIntegerValidator.getInstance().validate(localeVal, locale));
-        assertEquals("validate(A) pattern", expected, BigIntegerValidator.getInstance().validate(patternVal, pattern));
-        assertEquals("validate(A) both",    expected, BigIntegerValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertTrue("isValid(A) default", BigIntegerValidator.getInstance().isValid(defaultVal));
-        assertTrue("isValid(A) locale ", BigIntegerValidator.getInstance().isValid(localeVal, locale));
-        assertTrue("isValid(A) pattern", BigIntegerValidator.getInstance().isValid(patternVal, pattern));
-        assertTrue("isValid(A) both",    BigIntegerValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertNull("validate(B) default", BigIntegerValidator.getInstance().validate(XXXX));
-        assertNull("validate(B) locale ", BigIntegerValidator.getInstance().validate(XXXX, locale));
-        assertNull("validate(B) pattern", BigIntegerValidator.getInstance().validate(XXXX, pattern));
-        assertNull("validate(B) both",    BigIntegerValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN));
-
-        assertFalse("isValid(B) default", BigIntegerValidator.getInstance().isValid(XXXX));
-        assertFalse("isValid(B) locale ", BigIntegerValidator.getInstance().isValid(XXXX, locale));
-        assertFalse("isValid(B) pattern", BigIntegerValidator.getInstance().isValid(XXXX, pattern));
-        assertFalse("isValid(B) both",    BigIntegerValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN));
-    }
-
-    /**
      * Test BigInteger Range/Min/Max
      */
+    @Test
     public void testBigIntegerRangeMinMax() {
-        final BigIntegerValidator validator = (BigIntegerValidator)strictValidator;
-        final BigInteger number9  = validator.validate("9", "#");
+        final BigIntegerValidator validator = (BigIntegerValidator) strictValidator;
+        final BigInteger number9 = validator.validate("9", "#");
         final BigInteger number10 = validator.validate("10", "#");
         final BigInteger number11 = validator.validate("11", "#");
         final BigInteger number19 = validator.validate("19", "#");
@@ -118,20 +87,54 @@
         final BigInteger number21 = validator.validate("21", "#");
 
         // Test isInRange()
-        assertFalse("isInRange() < min",   validator.isInRange(number9,  10, 20));
-        assertTrue("isInRange() = min",    validator.isInRange(number10, 10, 20));
-        assertTrue("isInRange() in range", validator.isInRange(number11, 10, 20));
-        assertTrue("isInRange() = max",    validator.isInRange(number20, 10, 20));
-        assertFalse("isInRange() > max",   validator.isInRange(number21, 10, 20));
+        assertFalse(validator.isInRange(number9, 10, 20), "isInRange() < min");
+        assertTrue(validator.isInRange(number10, 10, 20), "isInRange() = min");
+        assertTrue(validator.isInRange(number11, 10, 20), "isInRange() in range");
+        assertTrue(validator.isInRange(number20, 10, 20), "isInRange() = max");
+        assertFalse(validator.isInRange(number21, 10, 20), "isInRange() > max");
 
         // Test minValue()
-        assertFalse("minValue() < min",    validator.minValue(number9,  10));
-        assertTrue("minValue() = min",     validator.minValue(number10, 10));
-        assertTrue("minValue() > min",     validator.minValue(number11, 10));
+        assertFalse(validator.minValue(number9, 10), "minValue() < min");
+        assertTrue(validator.minValue(number10, 10), "minValue() = min");
+        assertTrue(validator.minValue(number11, 10), "minValue() > min");
 
         // Test minValue()
-        assertTrue("maxValue() < max",     validator.maxValue(number19, 20));
-        assertTrue("maxValue() = max",     validator.maxValue(number20, 20));
-        assertFalse("maxValue() > max",    validator.maxValue(number21, 20));
+        assertTrue(validator.maxValue(number19, 20), "maxValue() < max");
+        assertTrue(validator.maxValue(number20, 20), "maxValue() = max");
+        assertFalse(validator.maxValue(number21, 20), "maxValue() > max");
+    }
+
+    /**
+     * Test BigIntegerValidator validate Methods
+     */
+    @Test
+    public void testBigIntegerValidatorMethods() {
+        final Locale locale = Locale.GERMAN;
+        final String pattern = "0,00,00";
+        final String patternVal = "1,23,45";
+        final String germanPatternVal = "1.23.45";
+        final String localeVal = "12.345";
+        final String defaultVal = "12,345";
+        final String XXXX = "XXXX";
+        final BigInteger expected = new BigInteger("12345");
+        assertEquals(expected, BigIntegerValidator.getInstance().validate(defaultVal), "validate(A) default");
+        assertEquals(expected, BigIntegerValidator.getInstance().validate(localeVal, locale), "validate(A) locale ");
+        assertEquals(expected, BigIntegerValidator.getInstance().validate(patternVal, pattern), "validate(A) pattern");
+        assertEquals(expected, BigIntegerValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN), "validate(A) both");
+
+        assertTrue(BigIntegerValidator.getInstance().isValid(defaultVal), "isValid(A) default");
+        assertTrue(BigIntegerValidator.getInstance().isValid(localeVal, locale), "isValid(A) locale ");
+        assertTrue(BigIntegerValidator.getInstance().isValid(patternVal, pattern), "isValid(A) pattern");
+        assertTrue(BigIntegerValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN), "isValid(A) both");
+
+        assertNull(BigIntegerValidator.getInstance().validate(XXXX), "validate(B) default");
+        assertNull(BigIntegerValidator.getInstance().validate(XXXX, locale), "validate(B) locale ");
+        assertNull(BigIntegerValidator.getInstance().validate(XXXX, pattern), "validate(B) pattern");
+        assertNull(BigIntegerValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN), "validate(B) both");
+
+        assertFalse(BigIntegerValidator.getInstance().isValid(XXXX), "isValid(B) default");
+        assertFalse(BigIntegerValidator.getInstance().isValid(XXXX, locale), "isValid(B) locale ");
+        assertFalse(BigIntegerValidator.getInstance().isValid(XXXX, pattern), "isValid(B) pattern");
+        assertFalse(BigIntegerValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN), "isValid(B) both");
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/ByteValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/ByteValidatorTest.java
index f348684..38104f4 100644
--- a/src/test/java/org/apache/commons/validator/routines/ByteValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/ByteValidatorTest.java
@@ -16,8 +16,16 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.util.Locale;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Test Case for ByteValidator.
  */
@@ -25,25 +33,19 @@
 
     private static final Byte BYTE_MIN_VAL = Byte.valueOf(Byte.MIN_VALUE);
     private static final Byte BYTE_MAX_VAL = Byte.valueOf(Byte.MAX_VALUE);
-    private static final String BYTE_MAX   =  "127";
-    private static final String BYTE_MAX_0 =  "127.99999999999999999999999"; // force double rounding
-    private static final String BYTE_MAX_1 =  "128";
-    private static final String BYTE_MIN   = "-128";
+    private static final String BYTE_MAX = "127";
+    private static final String BYTE_MAX_0 = "127.99999999999999999999999"; // force double rounding
+    private static final String BYTE_MAX_1 = "128";
+    private static final String BYTE_MIN = "-128";
     private static final String BYTE_MIN_0 = "-128.99999999999999999999999"; // force double rounding";
     private static final String BYTE_MIN_1 = "-129";
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public ByteValidatorTest(final String name) {
-        super(name);
-    }
 
     @Override
-    protected void setUp() throws Exception {
+    @BeforeEach
+    protected void setUp() {
         super.setUp();
 
-        validator       = new ByteValidator(false, 0);
+        validator = new ByteValidator(false, 0);
         strictValidator = new ByteValidator();
 
         testPattern = "#,###";
@@ -55,18 +57,18 @@
         minMinusOne = Long.valueOf(min.longValue() - 1);
 
         // testInvalidStrict()
-        invalidStrict = new String[] {null, "", "X", "X12", "12X", "1X2", "1.2", BYTE_MAX_1, BYTE_MIN_1, BYTE_MAX_0, BYTE_MIN_0};
+        invalidStrict = new String[] { null, "", "X", "X12", "12X", "1X2", "1.2", BYTE_MAX_1, BYTE_MIN_1, BYTE_MAX_0, BYTE_MIN_0 };
 
         // testInvalidNotStrict()
-        invalid       = new String[] {null, "", "X", "X12", BYTE_MAX_1, BYTE_MIN_1};
+        invalid = new String[] { null, "", "X", "X12", BYTE_MAX_1, BYTE_MIN_1 };
 
         // testValid()
-        testNumber    = Byte.valueOf((byte)123);
-        testZero      = Byte.valueOf((byte)0);
-        validStrict          = new String[] {"0", "123", ",123", BYTE_MAX, BYTE_MIN};
-        validStrictCompare   = new Number[] {testZero, testNumber, testNumber, BYTE_MAX_VAL, BYTE_MIN_VAL};
-        valid                = new String[] {"0", "123", ",123", ",123.5", "123X", BYTE_MAX, BYTE_MIN, BYTE_MAX_0, BYTE_MIN_0};
-        validCompare         = new Number[] {testZero, testNumber, testNumber, testNumber, testNumber, BYTE_MAX_VAL, BYTE_MIN_VAL, BYTE_MAX_VAL, BYTE_MIN_VAL};
+        testNumber = Byte.valueOf((byte) 123);
+        testZero = Byte.valueOf((byte) 0);
+        validStrict = new String[] { "0", "123", ",123", BYTE_MAX, BYTE_MIN };
+        validStrictCompare = new Number[] { testZero, testNumber, testNumber, BYTE_MAX_VAL, BYTE_MIN_VAL };
+        valid = new String[] { "0", "123", ",123", ",123.5", "123X", BYTE_MAX, BYTE_MIN, BYTE_MAX_0, BYTE_MIN_0 };
+        validCompare = new Number[] { testZero, testNumber, testNumber, testNumber, testNumber, BYTE_MAX_VAL, BYTE_MIN_VAL, BYTE_MAX_VAL, BYTE_MIN_VAL };
 
         testStringUS = ",123";
         testStringDE = ".123";
@@ -74,73 +76,75 @@
         // Localized Pattern test
         localeValue = testStringDE;
         localePattern = "#.###";
-        testLocale    = Locale.GERMANY;
+        testLocale = Locale.GERMANY;
         localeExpected = testNumber;
 
     }
 
     /**
-     * Test ByteValidator validate Methods
-     */
-    public void testByteValidatorMethods() {
-        final Locale locale     = Locale.GERMAN;
-        final String pattern    = "0,00";
-        final String patternVal = "1,23";
-        final String germanPatternVal = "1.23";
-        final String localeVal  = ".123";
-        final String defaultVal = ",123";
-        final String XXXX    = "XXXX";
-        final Byte expected = Byte.valueOf((byte)123);
-        assertEquals("validate(A) default", expected, ByteValidator.getInstance().validate(defaultVal));
-        assertEquals("validate(A) locale ", expected, ByteValidator.getInstance().validate(localeVal, locale));
-        assertEquals("validate(A) pattern", expected, ByteValidator.getInstance().validate(patternVal, pattern));
-        assertEquals("validate(A) both",    expected, ByteValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertTrue("isValid(A) default", ByteValidator.getInstance().isValid(defaultVal));
-        assertTrue("isValid(A) locale ", ByteValidator.getInstance().isValid(localeVal, locale));
-        assertTrue("isValid(A) pattern", ByteValidator.getInstance().isValid(patternVal, pattern));
-        assertTrue("isValid(A) both",    ByteValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertNull("validate(B) default", ByteValidator.getInstance().validate(XXXX));
-        assertNull("validate(B) locale ", ByteValidator.getInstance().validate(XXXX, locale));
-        assertNull("validate(B) pattern", ByteValidator.getInstance().validate(XXXX, pattern));
-        assertNull("validate(B) both",    ByteValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN));
-
-        assertFalse("isValid(B) default", ByteValidator.getInstance().isValid(XXXX));
-        assertFalse("isValid(B) locale ", ByteValidator.getInstance().isValid(XXXX, locale));
-        assertFalse("isValid(B) pattern", ByteValidator.getInstance().isValid(XXXX, pattern));
-        assertFalse("isValid(B) both",    ByteValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN));
-    }
-
-    /**
      * Test Byte Range/Min/Max
      */
+    @Test
     public void testByteRangeMinMax() {
-        final ByteValidator validator = (ByteValidator)strictValidator;
-        final Byte number9  = validator.validate("9", "#");
+        final ByteValidator validator = (ByteValidator) strictValidator;
+        final Byte number9 = validator.validate("9", "#");
         final Byte number10 = validator.validate("10", "#");
         final Byte number11 = validator.validate("11", "#");
         final Byte number19 = validator.validate("19", "#");
         final Byte number20 = validator.validate("20", "#");
         final Byte number21 = validator.validate("21", "#");
-        final byte min = (byte)10;
-        final byte max = (byte)20;
+        final byte min = (byte) 10;
+        final byte max = (byte) 20;
 
         // Test isInRange()
-        assertFalse("isInRange() < min",   validator.isInRange(number9,  min, max));
-        assertTrue("isInRange() = min",    validator.isInRange(number10, min, max));
-        assertTrue("isInRange() in range", validator.isInRange(number11, min, max));
-        assertTrue("isInRange() = max",    validator.isInRange(number20, min, max));
-        assertFalse("isInRange() > max",   validator.isInRange(number21, min, max));
+        assertFalse(validator.isInRange(number9, min, max), "isInRange() < min");
+        assertTrue(validator.isInRange(number10, min, max), "isInRange() = min");
+        assertTrue(validator.isInRange(number11, min, max), "isInRange() in range");
+        assertTrue(validator.isInRange(number20, min, max), "isInRange() = max");
+        assertFalse(validator.isInRange(number21, min, max), "isInRange() > max");
 
         // Test minValue()
-        assertFalse("minValue() < min",    validator.minValue(number9,  min));
-        assertTrue("minValue() = min",     validator.minValue(number10, min));
-        assertTrue("minValue() > min",     validator.minValue(number11, min));
+        assertFalse(validator.minValue(number9, min), "minValue() < min");
+        assertTrue(validator.minValue(number10, min), "minValue() = min");
+        assertTrue(validator.minValue(number11, min), "minValue() > min");
 
         // Test minValue()
-        assertTrue("maxValue() < max",     validator.maxValue(number19, max));
-        assertTrue("maxValue() = max",     validator.maxValue(number20, max));
-        assertFalse("maxValue() > max",    validator.maxValue(number21, max));
+        assertTrue(validator.maxValue(number19, max), "maxValue() < max");
+        assertTrue(validator.maxValue(number20, max), "maxValue() = max");
+        assertFalse(validator.maxValue(number21, max), "maxValue() > max");
+    }
+
+    /**
+     * Test ByteValidator validate Methods
+     */
+    @Test
+    public void testByteValidatorMethods() {
+        final Locale locale = Locale.GERMAN;
+        final String pattern = "0,00";
+        final String patternVal = "1,23";
+        final String germanPatternVal = "1.23";
+        final String localeVal = ".123";
+        final String defaultVal = ",123";
+        final String XXXX = "XXXX";
+        final Byte expected = Byte.valueOf((byte) 123);
+        assertEquals(expected, ByteValidator.getInstance().validate(defaultVal), "validate(A) default");
+        assertEquals(expected, ByteValidator.getInstance().validate(localeVal, locale), "validate(A) locale ");
+        assertEquals(expected, ByteValidator.getInstance().validate(patternVal, pattern), "validate(A) pattern");
+        assertEquals(expected, ByteValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN), "validate(A) both");
+
+        assertTrue(ByteValidator.getInstance().isValid(defaultVal), "isValid(A) default");
+        assertTrue(ByteValidator.getInstance().isValid(localeVal, locale), "isValid(A) locale ");
+        assertTrue(ByteValidator.getInstance().isValid(patternVal, pattern), "isValid(A) pattern");
+        assertTrue(ByteValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN), "isValid(A) both");
+
+        assertNull(ByteValidator.getInstance().validate(XXXX), "validate(B) default");
+        assertNull(ByteValidator.getInstance().validate(XXXX, locale), "validate(B) locale ");
+        assertNull(ByteValidator.getInstance().validate(XXXX, pattern), "validate(B) pattern");
+        assertNull(ByteValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN), "validate(B) both");
+
+        assertFalse(ByteValidator.getInstance().isValid(XXXX), "isValid(B) default");
+        assertFalse(ByteValidator.getInstance().isValid(XXXX, locale), "isValid(B) locale ");
+        assertFalse(ByteValidator.getInstance().isValid(XXXX, pattern), "isValid(B) pattern");
+        assertFalse(ByteValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN), "isValid(B) both");
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/CalendarValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/CalendarValidatorTest.java
index 0ec2ca3..59521de 100644
--- a/src/test/java/org/apache/commons/validator/routines/CalendarValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/CalendarValidatorTest.java
@@ -16,6 +16,12 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.text.DateFormat;
 import java.text.Format;
 import java.util.Calendar;
@@ -23,213 +29,29 @@
 import java.util.Locale;
 import java.util.TimeZone;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Test Case for CalendarValidator.
  */
 public class CalendarValidatorTest extends AbstractCalendarValidatorTest {
 
     private static final int DATE_2005_11_23 = 20051123;
-    private static final int TIME_12_03_45   = 120345;
+    private static final int TIME_12_03_45 = 120345;
 
     private CalendarValidator calValidator;
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public CalendarValidatorTest(final String name) {
-        super(name);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         calValidator = new CalendarValidator();
-        validator         = calValidator;
-    }
-
-    /**
-     * Test CalendarValidator validate Methods
-     */
-    public void testCalendarValidatorMethods() {
-        Locale.setDefault(Locale.US);
-        final Locale locale     = Locale.GERMAN;
-        final String pattern    = "yyyy-MM-dd";
-        final String patternVal = "2005-12-31";
-        final String germanVal     = "31 Dez 2005";
-        final String germanPattern = "dd MMM yyyy";
-        final String localeVal  = "31.12.2005";
-        final String defaultVal = "12/31/05";
-        final String XXXX    = "XXXX";
-        final Date expected = createCalendar(null, 20051231, 0).getTime();
-        assertEquals("validate(A) default", expected, CalendarValidator.getInstance().validate(defaultVal).getTime());
-        assertEquals("validate(A) locale ", expected, CalendarValidator.getInstance().validate(localeVal, locale).getTime());
-        assertEquals("validate(A) pattern", expected, CalendarValidator.getInstance().validate(patternVal, pattern).getTime());
-        assertEquals("validate(A) both",    expected, CalendarValidator.getInstance().validate(germanVal, germanPattern, Locale.GERMAN).getTime());
-
-        assertTrue("isValid(A) default", CalendarValidator.getInstance().isValid(defaultVal));
-        assertTrue("isValid(A) locale ", CalendarValidator.getInstance().isValid(localeVal, locale));
-        assertTrue("isValid(A) pattern", CalendarValidator.getInstance().isValid(patternVal, pattern));
-        assertTrue("isValid(A) both",    CalendarValidator.getInstance().isValid(germanVal, germanPattern, Locale.GERMAN));
-
-        assertNull("validate(B) default", CalendarValidator.getInstance().validate(XXXX));
-        assertNull("validate(B) locale ", CalendarValidator.getInstance().validate(XXXX, locale));
-        assertNull("validate(B) pattern", CalendarValidator.getInstance().validate(XXXX, pattern));
-        assertNull("validate(B) both",    CalendarValidator.getInstance().validate("31 Dec 2005", germanPattern, Locale.GERMAN));
-
-        assertFalse("isValid(B) default", CalendarValidator.getInstance().isValid(XXXX));
-        assertFalse("isValid(B) locale ", CalendarValidator.getInstance().isValid(XXXX, locale));
-        assertFalse("isValid(B) pattern", CalendarValidator.getInstance().isValid(XXXX, pattern));
-        assertFalse("isValid(B) both",    CalendarValidator.getInstance().isValid("31 Dec 2005", germanPattern, Locale.GERMAN));
-
-        // Test Time Zone
-        final TimeZone zone = (TimeZone.getDefault().getRawOffset() == EET.getRawOffset() ? EST : EET);
-        final Date expectedZone = createCalendar(zone, 20051231, 0).getTime();
-        assertFalse("default/EET same ", expected.getTime() == expectedZone.getTime());
-
-        assertEquals("validate(C) default", expectedZone, CalendarValidator.getInstance().validate(defaultVal, zone).getTime());
-        assertEquals("validate(C) locale ", expectedZone, CalendarValidator.getInstance().validate(localeVal, locale, zone).getTime());
-        assertEquals("validate(C) pattern", expectedZone, CalendarValidator.getInstance().validate(patternVal, pattern, zone).getTime());
-        assertEquals("validate(C) both",    expectedZone, CalendarValidator.getInstance().validate(germanVal, germanPattern, Locale.GERMAN, zone).getTime());
-    }
-
-    /**
-     * Test compare date methods
-     */
-    public void testCompare() {
-        final int sameTime = 124522;
-        final int testDate = 20050823;
-        final Calendar diffHour    = createCalendar(GMT, testDate, 115922);    // same date, different time
-        final Calendar diffMin     = createCalendar(GMT, testDate, 124422);    // same date, different time
-        final Calendar diffSec     = createCalendar(GMT, testDate, 124521);    // same date, different time
-
-        final Calendar value       = createCalendar(GMT, testDate, sameTime);   // test value
-        final Calendar cal20050824 = createCalendar(GMT, 20050824, sameTime);   // +1 day
-        final Calendar cal20050822 = createCalendar(GMT, 20050822, sameTime);   // -1 day
-
-        final Calendar cal20050830 = createCalendar(GMT, 20050830, sameTime);   // +1 week
-        final Calendar cal20050816 = createCalendar(GMT, 20050816, sameTime);   // -1 week
-
-        final Calendar cal20050901 = createCalendar(GMT, 20050901, sameTime);   // +1 month
-        final Calendar cal20050801 = createCalendar(GMT, 20050801, sameTime);   // same month
-        final Calendar cal20050731 = createCalendar(GMT, 20050731, sameTime);   // -1 month
-
-        final Calendar cal20051101 = createCalendar(GMT, 20051101, sameTime);   // +1 quarter (Feb Start)
-        final Calendar cal20051001 = createCalendar(GMT, 20051001, sameTime);   // +1 quarter
-        final Calendar cal20050701 = createCalendar(GMT, 20050701, sameTime);   // same quarter
-        final Calendar cal20050630 = createCalendar(GMT, 20050630, sameTime);   // -1 quarter
-
-        final Calendar cal20060101 = createCalendar(GMT, 20060101, sameTime);   // +1 year
-        final Calendar cal20050101 = createCalendar(GMT, 20050101, sameTime);   // same year
-        final Calendar cal20041231 = createCalendar(GMT, 20041231, sameTime);   // -1 year
-
-        assertEquals("hour GT", 1, calValidator.compare(value, diffHour, Calendar.HOUR_OF_DAY));
-        assertEquals("hour EQ", 0, calValidator.compare(value, diffMin,  Calendar.HOUR_OF_DAY));
-        assertEquals("mins GT", 1, calValidator.compare(value, diffMin,  Calendar.MINUTE));
-        assertEquals("mins EQ", 0, calValidator.compare(value, diffSec,  Calendar.MINUTE));
-        assertEquals("secs GT", 1, calValidator.compare(value, diffSec,  Calendar.SECOND));
-
-        assertEquals("date LT", -1, calValidator.compareDates(value, cal20050824)); // +1 day
-        assertEquals("date EQ", 0,  calValidator.compareDates(value, diffHour));    // same day, diff hour
-        assertEquals("date(B)", 0,  calValidator.compare(value, diffHour, Calendar.DAY_OF_YEAR));    // same day, diff hour
-        assertEquals("date GT", 1,  calValidator.compareDates(value, cal20050822)); // -1 day
-
-        assertEquals("week LT", -1, calValidator.compareWeeks(value, cal20050830)); // +1 week
-        assertEquals("week =1", 0,  calValidator.compareWeeks(value, cal20050824)); // +1 day
-        assertEquals("week =2", 0,  calValidator.compareWeeks(value, cal20050822)); // same week
-        assertEquals("week =3", 0,  calValidator.compare(value, cal20050822, Calendar.WEEK_OF_MONTH)); // same week
-        assertEquals("week =4", 0,  calValidator.compareWeeks(value, cal20050822)); // -1 day
-        assertEquals("week GT", 1,  calValidator.compareWeeks(value, cal20050816)); // -1 week
-
-        assertEquals("mnth LT", -1, calValidator.compareMonths(value, cal20050901)); // +1 month
-        assertEquals("mnth =1", 0,  calValidator.compareMonths(value, cal20050830)); // +1 week
-        assertEquals("mnth =2", 0,  calValidator.compareMonths(value, cal20050801)); // same month
-        assertEquals("mnth =3", 0,  calValidator.compareMonths(value, cal20050816)); // -1 week
-        assertEquals("mnth GT", 1,  calValidator.compareMonths(value, cal20050731)); // -1 month
-
-        assertEquals("qtrA <1", -1, calValidator.compareQuarters(value, cal20051101)); // +1 quarter (Feb)
-        assertEquals("qtrA <2", -1, calValidator.compareQuarters(value, cal20051001)); // +1 quarter
-        assertEquals("qtrA =1", 0,  calValidator.compareQuarters(value, cal20050901)); // +1 month
-        assertEquals("qtrA =2", 0,  calValidator.compareQuarters(value, cal20050701)); // same quarter
-        assertEquals("qtrA =3", 0,  calValidator.compareQuarters(value, cal20050731)); // -1 month
-        assertEquals("qtrA GT", 1,  calValidator.compareQuarters(value, cal20050630)); // -1 quarter
-
-        // Change quarter 1 to start in Feb
-        assertEquals("qtrB LT", -1, calValidator.compareQuarters(value, cal20051101, 2)); // +1 quarter (Feb)
-        assertEquals("qtrB =1", 0,  calValidator.compareQuarters(value, cal20051001, 2));  // same quarter
-        assertEquals("qtrB =2", 0,  calValidator.compareQuarters(value, cal20050901, 2)); // +1 month
-        assertEquals("qtrB =3", 1,  calValidator.compareQuarters(value, cal20050701, 2)); // same quarter
-        assertEquals("qtrB =4", 1,  calValidator.compareQuarters(value, cal20050731, 2)); // -1 month
-        assertEquals("qtrB GT", 1,  calValidator.compareQuarters(value, cal20050630, 2)); // -1 quarter
-
-        assertEquals("year LT", -1, calValidator.compareYears(value, cal20060101)); // +1 year
-        assertEquals("year EQ", 0,  calValidator.compareYears(value, cal20050101)); // same year
-        assertEquals("year GT", 1,  calValidator.compareYears(value, cal20041231)); // -1 year
-
-        // invalid compare
-        try {
-            calValidator.compare(value, value,  -1);
-            fail("Invalid Compare field - expected IllegalArgumentException to be thrown");
-        } catch (final IllegalArgumentException e) {
-            assertEquals("check message", "Invalid field: -1", e.getMessage());
-        }
-    }
-
-    /**
-     * Test Date/Time style Validator (there isn't an implementation for this)
-     */
-    public void testDateTimeStyle() {
-        // Set the default Locale
-        final Locale origDefault = Locale.getDefault();
-        Locale.setDefault(Locale.UK);
-
-        final AbstractCalendarValidator dateTimeValidator =
-            new AbstractCalendarValidator(true, DateFormat.SHORT, DateFormat.SHORT) {
-                private static final long serialVersionUID = 1L;
-
-            @Override
-            protected Object processParsedValue(final Object value, final Format formatter) {
-                return value;
-            }
-        };
-        assertTrue("validate(A) default", dateTimeValidator.isValid("31/12/05 14:23"));
-        assertTrue("validate(A) locale ", dateTimeValidator.isValid("12/31/05 2:23 PM", Locale.US));
-
-        // Restore the original default
-        Locale.setDefault(origDefault);
-    }
-
-    /**
-     * Test format methods
-     */
-    @Override
-    public void testFormat() {
-        // Set the default Locale
-        final Locale origDefault = Locale.getDefault();
-        Locale.setDefault(Locale.UK);
-
-        final Calendar cal20050101 = createCalendar(GMT, 20051231, 11500);
-        assertNull("null", calValidator.format(null));
-        assertEquals("default",  "31/12/05",         calValidator.format(cal20050101));
-        assertEquals("locale",   "12/31/05",         calValidator.format(cal20050101, Locale.US));
-        assertEquals("patternA", "2005-12-31 01:15", calValidator.format(cal20050101, "yyyy-MM-dd HH:mm"));
-        assertEquals("patternB", "2005-12-31 GMT",   calValidator.format(cal20050101, "yyyy-MM-dd z"));
-        assertEquals("both",     "31 Dez 2005",      calValidator.format(cal20050101, "dd MMM yyyy", Locale.GERMAN));
-
-        // EST Time Zone
-        assertEquals("EST default",  "30/12/05",         calValidator.format(cal20050101, EST));
-        assertEquals("EST locale",   "12/30/05",         calValidator.format(cal20050101, Locale.US, EST));
-        assertEquals("EST patternA", "2005-12-30 20:15", calValidator.format(cal20050101, "yyyy-MM-dd HH:mm", EST));
-        assertEquals("EST patternB", "2005-12-30 EST",   calValidator.format(cal20050101, "yyyy-MM-dd z", EST));
-        assertEquals("EST both",     "30 Dez 2005",      calValidator.format(cal20050101, "dd MMM yyyy", Locale.GERMAN, EST));
-
-        // Restore the original default
-        Locale.setDefault(origDefault);
+        validator = calValidator;
     }
 
     /**
      * Test adjustToTimeZone() method
      */
+    @Test
     public void testAdjustToTimeZone() {
 
         final Calendar calEST = createCalendar(EST, DATE_2005_11_23, TIME_12_03_45);
@@ -242,36 +64,218 @@
         final Date dateCET = calCET.getTime();
 
         // Check the dates don't match
-        assertFalse("Check GMT != CET", dateGMT.getTime() == dateCET.getTime());
-        assertFalse("Check GMT != EST", dateGMT.getTime() == dateEST.getTime());
-        assertFalse("Check CET != EST", dateCET.getTime() == dateEST.getTime());
+        assertFalse(dateGMT.getTime() == dateCET.getTime(), "Check GMT != CET");
+        assertFalse(dateGMT.getTime() == dateEST.getTime(), "Check GMT != EST");
+        assertFalse(dateCET.getTime() == dateEST.getTime(), "Check CET != EST");
 
         // EST to GMT and back
         CalendarValidator.adjustToTimeZone(calEST, GMT);
-        assertEquals("EST to GMT", dateGMT, calEST.getTime());
-        assertFalse("Check EST = GMT", dateEST == calEST.getTime());
+        assertEquals(dateGMT, calEST.getTime(), "EST to GMT");
+        assertFalse(dateEST == calEST.getTime(), "Check EST = GMT");
         CalendarValidator.adjustToTimeZone(calEST, EST);
-        assertEquals("back to EST", dateEST, calEST.getTime());
-        assertFalse("Check EST != GMT", dateGMT == calEST.getTime());
+        assertEquals(dateEST, calEST.getTime(), "back to EST");
+        assertFalse(dateGMT == calEST.getTime(), "Check EST != GMT");
 
         // CET to GMT and back
         CalendarValidator.adjustToTimeZone(calCET, GMT);
-        assertEquals("CET to GMT", dateGMT, calCET.getTime());
-        assertFalse("Check CET = GMT", dateCET == calCET.getTime());
+        assertEquals(dateGMT, calCET.getTime(), "CET to GMT");
+        assertFalse(dateCET == calCET.getTime(), "Check CET = GMT");
         CalendarValidator.adjustToTimeZone(calCET, EET);
-        assertEquals("back to CET", dateCET, calCET.getTime());
-        assertFalse("Check CET != GMT", dateGMT == calCET.getTime());
+        assertEquals(dateCET, calCET.getTime(), "back to CET");
+        assertFalse(dateGMT == calCET.getTime(), "Check CET != GMT");
 
         // Adjust to TimeZone with Same rules
         final Calendar calUTC = createCalendar(UTC, DATE_2005_11_23, TIME_12_03_45);
-        assertTrue("SAME: UTC = GMT",  UTC.hasSameRules(GMT));
-        assertEquals("SAME: Check time (A)", calUTC.getTime(), calGMT.getTime());
-        assertFalse("SAME: Check GMT(A)", GMT.equals(calUTC.getTimeZone()));
-        assertTrue("SAME: Check UTC(A)",  UTC.equals(calUTC.getTimeZone()));
+        assertTrue(UTC.hasSameRules(GMT), "SAME: UTC = GMT");
+        assertEquals(calUTC.getTime(), calGMT.getTime(), "SAME: Check time (A)");
+        assertFalse(GMT.equals(calUTC.getTimeZone()), "SAME: Check GMT(A)");
+        assertTrue(UTC.equals(calUTC.getTimeZone()), "SAME: Check UTC(A)");
         CalendarValidator.adjustToTimeZone(calUTC, GMT);
-        assertEquals("SAME: Check time (B)", calUTC.getTime(), calGMT.getTime());
-        assertTrue("SAME: Check GMT(B)", GMT.equals(calUTC.getTimeZone()));
-        assertFalse("SAME: Check UTC(B)",  UTC.equals(calUTC.getTimeZone()));
+        assertEquals(calUTC.getTime(), calGMT.getTime(), "SAME: Check time (B)");
+        assertTrue(GMT.equals(calUTC.getTimeZone()), "SAME: Check GMT(B)");
+        assertFalse(UTC.equals(calUTC.getTimeZone()), "SAME: Check UTC(B)");
+    }
+
+    /**
+     * Test CalendarValidator validate Methods
+     */
+    @Test
+    public void testCalendarValidatorMethods() {
+        Locale.setDefault(Locale.US);
+        final Locale locale = Locale.GERMAN;
+        final String pattern = "yyyy-MM-dd";
+        final String patternVal = "2005-12-31";
+        final String germanVal = "31 Dez 2005";
+        final String germanPattern = "dd MMM yyyy";
+        final String localeVal = "31.12.2005";
+        final String defaultVal = "12/31/05";
+        final String XXXX = "XXXX";
+        final Date expected = createCalendar(null, 20051231, 0).getTime();
+        assertEquals(expected, CalendarValidator.getInstance().validate(defaultVal).getTime(), "validate(A) default");
+        assertEquals(expected, CalendarValidator.getInstance().validate(localeVal, locale).getTime(), "validate(A) locale ");
+        assertEquals(expected, CalendarValidator.getInstance().validate(patternVal, pattern).getTime(), "validate(A) pattern");
+        assertEquals(expected, CalendarValidator.getInstance().validate(germanVal, germanPattern, Locale.GERMAN).getTime(), "validate(A) both");
+
+        assertTrue(CalendarValidator.getInstance().isValid(defaultVal), "isValid(A) default");
+        assertTrue(CalendarValidator.getInstance().isValid(localeVal, locale), "isValid(A) locale ");
+        assertTrue(CalendarValidator.getInstance().isValid(patternVal, pattern), "isValid(A) pattern");
+        assertTrue(CalendarValidator.getInstance().isValid(germanVal, germanPattern, Locale.GERMAN), "isValid(A) both");
+
+        assertNull(CalendarValidator.getInstance().validate(XXXX), "validate(B) default");
+        assertNull(CalendarValidator.getInstance().validate(XXXX, locale), "validate(B) locale ");
+        assertNull(CalendarValidator.getInstance().validate(XXXX, pattern), "validate(B) pattern");
+        assertNull(CalendarValidator.getInstance().validate("31 Dec 2005", germanPattern, Locale.GERMAN), "validate(B) both");
+
+        assertFalse(CalendarValidator.getInstance().isValid(XXXX), "isValid(B) default");
+        assertFalse(CalendarValidator.getInstance().isValid(XXXX, locale), "isValid(B) locale ");
+        assertFalse(CalendarValidator.getInstance().isValid(XXXX, pattern), "isValid(B) pattern");
+        assertFalse(CalendarValidator.getInstance().isValid("31 Dec 2005", germanPattern, Locale.GERMAN), "isValid(B) both");
+
+        // Test Time Zone
+        final TimeZone zone = TimeZone.getDefault().getRawOffset() == EET.getRawOffset() ? EST : EET;
+        final Date expectedZone = createCalendar(zone, 20051231, 0).getTime();
+        assertFalse(expected.getTime() == expectedZone.getTime(), "default/EET same ");
+
+        assertEquals(expectedZone, CalendarValidator.getInstance().validate(defaultVal, zone).getTime(), "validate(C) default");
+        assertEquals(expectedZone, CalendarValidator.getInstance().validate(localeVal, locale, zone).getTime(), "validate(C) locale ");
+        assertEquals(expectedZone, CalendarValidator.getInstance().validate(patternVal, pattern, zone).getTime(), "validate(C) pattern");
+        assertEquals(expectedZone, CalendarValidator.getInstance().validate(germanVal, germanPattern, Locale.GERMAN, zone).getTime(), "validate(C) both");
+    }
+
+    /**
+     * Test compare date methods
+     */
+    @Test
+    public void testCompare() {
+        final int sameTime = 124522;
+        final int testDate = 20050823;
+        final Calendar diffHour = createCalendar(GMT, testDate, 115922); // same date, different time
+        final Calendar diffMin = createCalendar(GMT, testDate, 124422); // same date, different time
+        final Calendar diffSec = createCalendar(GMT, testDate, 124521); // same date, different time
+
+        final Calendar value = createCalendar(GMT, testDate, sameTime); // test value
+        final Calendar cal20050824 = createCalendar(GMT, 20050824, sameTime); // +1 day
+        final Calendar cal20050822 = createCalendar(GMT, 20050822, sameTime); // -1 day
+
+        final Calendar cal20050830 = createCalendar(GMT, 20050830, sameTime); // +1 week
+        final Calendar cal20050816 = createCalendar(GMT, 20050816, sameTime); // -1 week
+
+        final Calendar cal20050901 = createCalendar(GMT, 20050901, sameTime); // +1 month
+        final Calendar cal20050801 = createCalendar(GMT, 20050801, sameTime); // same month
+        final Calendar cal20050731 = createCalendar(GMT, 20050731, sameTime); // -1 month
+
+        final Calendar cal20051101 = createCalendar(GMT, 20051101, sameTime); // +1 quarter (Feb Start)
+        final Calendar cal20051001 = createCalendar(GMT, 20051001, sameTime); // +1 quarter
+        final Calendar cal20050701 = createCalendar(GMT, 20050701, sameTime); // same quarter
+        final Calendar cal20050630 = createCalendar(GMT, 20050630, sameTime); // -1 quarter
+
+        final Calendar cal20060101 = createCalendar(GMT, 20060101, sameTime); // +1 year
+        final Calendar cal20050101 = createCalendar(GMT, 20050101, sameTime); // same year
+        final Calendar cal20041231 = createCalendar(GMT, 20041231, sameTime); // -1 year
+
+        assertEquals(1, calValidator.compare(value, diffHour, Calendar.HOUR_OF_DAY), "hour GT");
+        assertEquals(0, calValidator.compare(value, diffMin, Calendar.HOUR_OF_DAY), "hour EQ");
+        assertEquals(1, calValidator.compare(value, diffMin, Calendar.MINUTE), "mins GT");
+        assertEquals(0, calValidator.compare(value, diffSec, Calendar.MINUTE), "mins EQ");
+        assertEquals(1, calValidator.compare(value, diffSec, Calendar.SECOND), "secs GT");
+
+        assertEquals(-1, calValidator.compareDates(value, cal20050824), "date LT"); // +1 day
+        assertEquals(0, calValidator.compareDates(value, diffHour), "date EQ"); // same day, diff hour
+        assertEquals(0, calValidator.compare(value, diffHour, Calendar.DAY_OF_YEAR), "date(B)"); // same day, diff hour
+        assertEquals(1, calValidator.compareDates(value, cal20050822), "date GT"); // -1 day
+
+        assertEquals(-1, calValidator.compareWeeks(value, cal20050830), "week LT"); // +1 week
+        assertEquals(0, calValidator.compareWeeks(value, cal20050824), "week =1"); // +1 day
+        assertEquals(0, calValidator.compareWeeks(value, cal20050822), "week =2"); // same week
+        assertEquals(0, calValidator.compare(value, cal20050822, Calendar.WEEK_OF_MONTH), "week =3"); // same week
+        assertEquals(0, calValidator.compareWeeks(value, cal20050822), "week =4"); // -1 day
+        assertEquals(1, calValidator.compareWeeks(value, cal20050816), "week GT"); // -1 week
+
+        assertEquals(-1, calValidator.compareMonths(value, cal20050901), "mnth LT"); // +1 month
+        assertEquals(0, calValidator.compareMonths(value, cal20050830), "mnth =1"); // +1 week
+        assertEquals(0, calValidator.compareMonths(value, cal20050801), "mnth =2"); // same month
+        assertEquals(0, calValidator.compareMonths(value, cal20050816), "mnth =3"); // -1 week
+        assertEquals(1, calValidator.compareMonths(value, cal20050731), "mnth GT"); // -1 month
+
+        assertEquals(-1, calValidator.compareQuarters(value, cal20051101), "qtrA <1"); // +1 quarter (Feb)
+        assertEquals(-1, calValidator.compareQuarters(value, cal20051001), "qtrA <2"); // +1 quarter
+        assertEquals(0, calValidator.compareQuarters(value, cal20050901), "qtrA =1"); // +1 month
+        assertEquals(0, calValidator.compareQuarters(value, cal20050701), "qtrA =2"); // same quarter
+        assertEquals(0, calValidator.compareQuarters(value, cal20050731), "qtrA =3"); // -1 month
+        assertEquals(1, calValidator.compareQuarters(value, cal20050630), "qtrA GT"); // -1 quarter
+
+        // Change quarter 1 to start in Feb
+        assertEquals(-1, calValidator.compareQuarters(value, cal20051101, 2), "qtrB LT"); // +1 quarter (Feb)
+        assertEquals(0, calValidator.compareQuarters(value, cal20051001, 2), "qtrB =1"); // same quarter
+        assertEquals(0, calValidator.compareQuarters(value, cal20050901, 2), "qtrB =2"); // +1 month
+        assertEquals(1, calValidator.compareQuarters(value, cal20050701, 2), "qtrB =3"); // same quarter
+        assertEquals(1, calValidator.compareQuarters(value, cal20050731, 2), "qtrB =4"); // -1 month
+        assertEquals(1, calValidator.compareQuarters(value, cal20050630, 2), "qtrB GT"); // -1 quarter
+
+        assertEquals(-1, calValidator.compareYears(value, cal20060101), "year LT"); // +1 year
+        assertEquals(0, calValidator.compareYears(value, cal20050101), "year EQ"); // same year
+        assertEquals(1, calValidator.compareYears(value, cal20041231), "year GT"); // -1 year
+
+        // invalid compare
+        try {
+            calValidator.compare(value, value, -1);
+            fail("Invalid Compare field - expected IllegalArgumentException to be thrown");
+        } catch (final IllegalArgumentException e) {
+            assertEquals(e.getMessage(), "Invalid field: -1", "check message");
+        }
+    }
+
+    /**
+     * Test Date/Time style Validator (there isn't an implementation for this)
+     */
+    @Test
+    public void testDateTimeStyle() {
+        // Set the default Locale
+        final Locale origDefault = Locale.getDefault();
+        Locale.setDefault(Locale.UK);
+
+        final AbstractCalendarValidator dateTimeValidator = new AbstractCalendarValidator(true, DateFormat.SHORT, DateFormat.SHORT) {
+            private static final long serialVersionUID = 1L;
+
+            @Override
+            protected Object processParsedValue(final Object value, final Format formatter) {
+                return value;
+            }
+        };
+        assertTrue(dateTimeValidator.isValid("31/12/05 14:23"), "validate(A) default");
+        assertTrue(dateTimeValidator.isValid("12/31/05 2:23 PM", Locale.US), "validate(A) locale ");
+
+        // Restore the original default
+        Locale.setDefault(origDefault);
+    }
+
+    /**
+     * Test format methods
+     */
+    @Override
+    @Test
+    public void testFormat() {
+        // Set the default Locale
+        final Locale origDefault = Locale.getDefault();
+        Locale.setDefault(Locale.UK);
+
+        final Calendar cal20050101 = createCalendar(GMT, 20051231, 11500);
+        assertNull(calValidator.format(null), "null");
+        assertEquals("31/12/05", calValidator.format(cal20050101), "default");
+        assertEquals("12/31/05", calValidator.format(cal20050101, Locale.US), "locale");
+        assertEquals(calValidator.format(cal20050101, "yyyy-MM-dd HH:mm"), "2005-12-31 01:15", "patternA");
+        assertEquals(calValidator.format(cal20050101, "yyyy-MM-dd z"), "2005-12-31 GMT", "patternB");
+        assertEquals("31 Dez 2005", calValidator.format(cal20050101, "dd MMM yyyy", Locale.GERMAN), "both");
+
+        // EST Time Zone
+        assertEquals("30/12/05", calValidator.format(cal20050101, EST), "EST default");
+        assertEquals("12/30/05", calValidator.format(cal20050101, Locale.US, EST), "EST locale");
+        assertEquals(calValidator.format(cal20050101, "yyyy-MM-dd HH:mm", EST), "2005-12-30 20:15", "EST patternA");
+        assertEquals(calValidator.format(cal20050101, "yyyy-MM-dd z", EST), "2005-12-30 EST", "EST patternB");
+        assertEquals("30 Dez 2005", calValidator.format(cal20050101, "dd MMM yyyy", Locale.GERMAN, EST), "EST both");
+
+        // Restore the original default
+        Locale.setDefault(origDefault);
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/CodeValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/CodeValidatorTest.java
index 995453d..5e35bda 100644
--- a/src/test/java/org/apache/commons/validator/routines/CodeValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/CodeValidatorTest.java
@@ -16,246 +16,232 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import org.apache.commons.validator.routines.checkdigit.CheckDigit;
 import org.apache.commons.validator.routines.checkdigit.EAN13CheckDigit;
-
-import junit.framework.TestCase;
+import org.junit.jupiter.api.Test;
 
 /**
  * CodeValidatorTest.java.
- *
- * @since 1.4
  */
-public class CodeValidatorTest extends TestCase {
-
-    /**
-     * Construct a test with the specified name.
-     * @param name The name of the test
-     */
-    public CodeValidatorTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * @see junit.framework.TestCase#setUp()
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
-
-    /**
-     * @see junit.framework.TestCase#tearDown()
-     */
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
+public class CodeValidatorTest {
 
     /**
      * Test Check Digit.
      */
+    @Test
     public void testCheckDigit() {
-        CodeValidator validator = new CodeValidator((String)null, -1, -1, (CheckDigit)null);
+        CodeValidator validator = new CodeValidator((String) null, -1, -1, (CheckDigit) null);
         final String invalidEAN = "9781930110992";
-        final String validEAN   = "9781930110991";
+        final String validEAN = "9781930110991";
 
         // Test no CheckDigit (i.e. null)
-        assertNull("No CheckDigit", validator.getCheckDigit());
-        assertEquals("No CheckDigit invalid", invalidEAN, validator.validate(invalidEAN));
-        assertEquals("No CheckDigit valid",     validEAN, validator.validate(validEAN));
-        assertEquals("No CheckDigit (is) invalid",  true, validator.isValid(invalidEAN));
-        assertEquals("No CheckDigit (is) valid",    true, validator.isValid(validEAN));
+        assertNull(validator.getCheckDigit(), "No CheckDigit");
+        assertEquals(invalidEAN, validator.validate(invalidEAN), "No CheckDigit invalid");
+        assertEquals(validEAN, validator.validate(validEAN), "No CheckDigit valid");
+        assertTrue(validator.isValid(invalidEAN), "No CheckDigit (is) invalid");
+        assertTrue(validator.isValid(validEAN), "No CheckDigit (is) valid");
 
         // Use the EAN-13 check digit routine
-        validator = new CodeValidator((String)null, -1, EAN13CheckDigit.EAN13_CHECK_DIGIT);
+        validator = new CodeValidator((String) null, -1, EAN13CheckDigit.EAN13_CHECK_DIGIT);
 
-        assertNotNull("EAN CheckDigit", validator.getCheckDigit());
-        assertEquals("EAN CheckDigit invalid",       null, validator.validate(invalidEAN));
-        assertEquals("EAN CheckDigit valid",     validEAN, validator.validate(validEAN));
-        assertEquals("EAN CheckDigit (is) invalid", false, validator.isValid(invalidEAN));
-        assertEquals("EAN CheckDigit (is) valid",    true, validator.isValid(validEAN));
-        assertEquals("EAN CheckDigit ex",            null, validator.validate("978193011099X"));
-    }
-
-    /**
-     * Test the minimum/maximum length
-     */
-    public void testLength() {
-        CodeValidator validator = new CodeValidator((String)null, -1, -1, (CheckDigit)null);
-        final String length_10  = "1234567890";
-        final String length_11  = "12345678901";
-        final String length_12  = "123456789012";
-        final String length_20  = "12345678901234567890";
-        final String length_21  = "123456789012345678901";
-        final String length_22  = "1234567890123456789012";
-
-        assertEquals("No min", -1, validator.getMinLength());
-        assertEquals("No max", -1, validator.getMaxLength());
-
-        assertEquals("No Length 10", length_10, validator.validate(length_10));
-        assertEquals("No Length 11", length_11, validator.validate(length_11));
-        assertEquals("No Length 12", length_12, validator.validate(length_12));
-        assertEquals("No Length 20", length_20, validator.validate(length_20));
-        assertEquals("No Length 21", length_21, validator.validate(length_21));
-        assertEquals("No Length 22", length_22, validator.validate(length_22));
-
-        validator = new CodeValidator((String)null, 11, -1, (CheckDigit)null);
-        assertEquals("Min 11 - min", 11, validator.getMinLength());
-        assertEquals("Min 11 - max", -1, validator.getMaxLength());
-        assertEquals("Min 11 - 10", null,      validator.validate(length_10));
-        assertEquals("Min 11 - 11", length_11, validator.validate(length_11));
-        assertEquals("Min 11 - 12", length_12, validator.validate(length_12));
-        assertEquals("Min 11 - 20", length_20, validator.validate(length_20));
-        assertEquals("Min 11 - 21", length_21, validator.validate(length_21));
-        assertEquals("Min 11 - 22", length_22, validator.validate(length_22));
-
-        validator = new CodeValidator((String)null, -1, 21, (CheckDigit)null);
-        assertEquals("Max 21 - min", -1, validator.getMinLength());
-        assertEquals("Max 21 - max", 21, validator.getMaxLength());
-        assertEquals("Max 21 - 10", length_10, validator.validate(length_10));
-        assertEquals("Max 21 - 11", length_11, validator.validate(length_11));
-        assertEquals("Max 21 - 12", length_12, validator.validate(length_12));
-        assertEquals("Max 21 - 20", length_20, validator.validate(length_20));
-        assertEquals("Max 21 - 21", length_21, validator.validate(length_21));
-        assertEquals("Max 21 - 22", null,      validator.validate(length_22));
-
-        validator = new CodeValidator((String)null, 11, 21, (CheckDigit)null);
-        assertEquals("Min 11 / Max 21 - min", 11, validator.getMinLength());
-        assertEquals("Min 11 / Max 21 - max", 21, validator.getMaxLength());
-        assertEquals("Min 11 / Max 21 - 10", null,      validator.validate(length_10));
-        assertEquals("Min 11 / Max 21 - 11", length_11, validator.validate(length_11));
-        assertEquals("Min 11 / Max 21 - 12", length_12, validator.validate(length_12));
-        assertEquals("Min 11 / Max 21 - 20", length_20, validator.validate(length_20));
-        assertEquals("Min 11 / Max 21 - 21", length_21, validator.validate(length_21));
-        assertEquals("Min 11 / Max 21 - 22", null,      validator.validate(length_22));
-
-        validator = new CodeValidator((String)null, 11, 11, (CheckDigit)null);
-        assertEquals("Exact 11 - min", 11, validator.getMinLength());
-        assertEquals("Exact 11 - max", 11, validator.getMaxLength());
-        assertEquals("Exact 11 - 10", null,      validator.validate(length_10));
-        assertEquals("Exact 11 - 11", length_11, validator.validate(length_11));
-        assertEquals("Exact 11 - 12", null,      validator.validate(length_12));
+        assertNotNull(validator.getCheckDigit(), "EAN CheckDigit");
+        assertNull(validator.validate(invalidEAN), "EAN CheckDigit invalid");
+        assertEquals(validEAN, validator.validate(validEAN), "EAN CheckDigit valid");
+        assertFalse(validator.isValid(invalidEAN), "EAN CheckDigit (is) invalid");
+        assertTrue(validator.isValid(validEAN), "EAN CheckDigit (is) valid");
+        assertNull(validator.validate("978193011099X"), "EAN CheckDigit ex");
     }
 
     /**
      * Test Regular Expression.
      */
-    public void testRegex() {
-        CodeValidator validator = new CodeValidator((String)null, -1, -1, (CheckDigit)null);
-
-        final String value2  = "12";
-        final String value3  = "123";
-        final String value4  = "1234";
-        final String value5  = "12345";
-        final String invalid = "12a4";
-
-        // No Regular Expression
-        assertNull("No Regex", validator.getRegexValidator());
-        assertEquals("No Regex 2", value2, validator.validate(value2));
-        assertEquals("No Regex 3", value3, validator.validate(value3));
-        assertEquals("No Regex 4", value4, validator.validate(value4));
-        assertEquals("No Regex 5", value5, validator.validate(value5));
-        assertEquals("No Regex invalid", invalid, validator.validate(invalid));
-
-        // Regular Expression
-        String regex = "^([0-9]{3,4})$";
-        validator = new CodeValidator(regex, -1, -1, (CheckDigit)null);
-        assertNotNull("No Regex", validator.getRegexValidator());
-        assertEquals("Regex 2", null,   validator.validate(value2));
-        assertEquals("Regex 3", value3, validator.validate(value3));
-        assertEquals("Regex 4", value4, validator.validate(value4));
-        assertEquals("Regex 5", null,   validator.validate(value5));
-        assertEquals("Regex invalid", null, validator.validate(invalid));
-
-        // Reformatted
-        regex = "^([0-9]{3})(?:[-\\s])([0-9]{3})$";
-        validator = new CodeValidator(new RegexValidator(regex), 6, (CheckDigit)null);
-        assertEquals("Reformat 123-456", "123456", validator.validate("123-456"));
-        assertEquals("Reformat 123 456", "123456", validator.validate("123 456"));
-        assertEquals("Reformat 123456",  null,     validator.validate("123456"));
-        assertEquals("Reformat 123.456", null,     validator.validate("123.456"));
-
-        regex = "^(?:([0-9]{3})(?:[-\\s])([0-9]{3}))|([0-9]{6})$";
-        validator = new CodeValidator(new RegexValidator(regex), 6, (CheckDigit)null);
-        assertEquals("Reformat 2 Regex",  "RegexValidator{" + regex + "}", validator.getRegexValidator().toString());
-        assertEquals("Reformat 2 123-456", "123456", validator.validate("123-456"));
-        assertEquals("Reformat 2 123 456", "123456", validator.validate("123 456"));
-        assertEquals("Reformat 2 123456",  "123456", validator.validate("123456"));
-
-    }
-
-    /**
-     * Test Regular Expression.
-     */
-    public void testNoInput() {
-        final CodeValidator validator = new CodeValidator((String)null, -1, -1, (CheckDigit)null);
-        assertEquals("Null",         null, validator.validate(null));
-        assertEquals("Zero Length",  null, validator.validate(""));
-        assertEquals("Spaces",       null, validator.validate("   "));
-        assertEquals("Trimmed",      "A",  validator.validate(" A  "));
-    }
-
-    public void testValidator294_1() {
-        CodeValidator validator = new CodeValidator((String)null, 0, -1, (CheckDigit)null);
-        assertEquals("Null",         null, validator.validate(null));
-        validator = new CodeValidator((String)null, -1, 0, (CheckDigit)null);
-        assertEquals("Null",         null, validator.validate(null));
-    }
-
-    public void testValidator294_2() {
-        final CodeValidator validator = new CodeValidator((String)null, -1, 0, (CheckDigit)null);
-        assertEquals("Null",         null, validator.validate(null));
-    }
-
-    /**
-     * Test Regular Expression.
-     */
+    @Test
     public void testConstructors() {
         CodeValidator validator;
         final RegexValidator regex = new RegexValidator("^[0-9]*$");
 
         // Constructor 1
         validator = new CodeValidator(regex, EAN13CheckDigit.EAN13_CHECK_DIGIT);
-        assertEquals("Constructor 1 - regex",      regex, validator.getRegexValidator());
-        assertEquals("Constructor 1 - min length", -1, validator.getMinLength());
-        assertEquals("Constructor 1 - max length", -1, validator.getMaxLength());
-        assertEquals("Constructor 1 - check digit", EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit());
+        assertEquals(regex, validator.getRegexValidator(), "Constructor 1 - regex");
+        assertEquals(-1, validator.getMinLength(), "Constructor 1 - min length");
+        assertEquals(-1, validator.getMaxLength(), "Constructor 1 - max length");
+        assertEquals(EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit(), "Constructor 1 - check digit");
 
         // Constructor 2
         validator = new CodeValidator(regex, 13, EAN13CheckDigit.EAN13_CHECK_DIGIT);
-        assertEquals("Constructor 2 - regex",      regex, validator.getRegexValidator());
-        assertEquals("Constructor 2 - min length", 13, validator.getMinLength());
-        assertEquals("Constructor 2 - max length", 13, validator.getMaxLength());
-        assertEquals("Constructor 2 - check digit", EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit());
+        assertEquals(regex, validator.getRegexValidator(), "Constructor 2 - regex");
+        assertEquals(13, validator.getMinLength(), "Constructor 2 - min length");
+        assertEquals(13, validator.getMaxLength(), "Constructor 2 - max length");
+        assertEquals(EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit(), "Constructor 2 - check digit");
 
         // Constructor 3
         validator = new CodeValidator(regex, 10, 20, EAN13CheckDigit.EAN13_CHECK_DIGIT);
-        assertEquals("Constructor 3 - regex",      regex, validator.getRegexValidator());
-        assertEquals("Constructor 3 - min length", 10, validator.getMinLength());
-        assertEquals("Constructor 3 - max length", 20, validator.getMaxLength());
-        assertEquals("Constructor 3 - check digit", EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit());
+        assertEquals(regex, validator.getRegexValidator(), "Constructor 3 - regex");
+        assertEquals(10, validator.getMinLength(), "Constructor 3 - min length");
+        assertEquals(20, validator.getMaxLength(), "Constructor 3 - max length");
+        assertEquals(EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit(), "Constructor 3 - check digit");
 
         // Constructor 4
         validator = new CodeValidator("^[0-9]*$", EAN13CheckDigit.EAN13_CHECK_DIGIT);
-        assertEquals("Constructor 4 - regex",      "RegexValidator{^[0-9]*$}", validator.getRegexValidator().toString());
-        assertEquals("Constructor 4 - min length", -1, validator.getMinLength());
-        assertEquals("Constructor 4 - max length", -1, validator.getMaxLength());
-        assertEquals("Constructor 4 - check digit", EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit());
+        assertEquals(validator.getRegexValidator().toString(), "RegexValidator{^[0-9]*$}", "Constructor 4 - regex");
+        assertEquals(-1, validator.getMinLength(), "Constructor 4 - min length");
+        assertEquals(-1, validator.getMaxLength(), "Constructor 4 - max length");
+        assertEquals(EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit(), "Constructor 4 - check digit");
 
         // Constructor 5
         validator = new CodeValidator("^[0-9]*$", 13, EAN13CheckDigit.EAN13_CHECK_DIGIT);
-        assertEquals("Constructor 5 - regex",      "RegexValidator{^[0-9]*$}", validator.getRegexValidator().toString());
-        assertEquals("Constructor 5 - min length", 13, validator.getMinLength());
-        assertEquals("Constructor 5 - max length", 13, validator.getMaxLength());
-        assertEquals("Constructor 5 - check digit", EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit());
+        assertEquals(validator.getRegexValidator().toString(), "RegexValidator{^[0-9]*$}", "Constructor 5 - regex");
+        assertEquals(13, validator.getMinLength(), "Constructor 5 - min length");
+        assertEquals(13, validator.getMaxLength(), "Constructor 5 - max length");
+        assertEquals(EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit(), "Constructor 5 - check digit");
 
         // Constructor 6
         validator = new CodeValidator("^[0-9]*$", 10, 20, EAN13CheckDigit.EAN13_CHECK_DIGIT);
-        assertEquals("Constructor 6 - regex",      "RegexValidator{^[0-9]*$}", validator.getRegexValidator().toString());
-        assertEquals("Constructor 6 - min length", 10, validator.getMinLength());
-        assertEquals("Constructor 6 - max length", 20, validator.getMaxLength());
-        assertEquals("Constructor 6 - check digit", EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit());
+        assertEquals(validator.getRegexValidator().toString(), "RegexValidator{^[0-9]*$}", "Constructor 6 - regex");
+        assertEquals(10, validator.getMinLength(), "Constructor 6 - min length");
+        assertEquals(20, validator.getMaxLength(), "Constructor 6 - max length");
+        assertEquals(EAN13CheckDigit.EAN13_CHECK_DIGIT, validator.getCheckDigit(), "Constructor 6 - check digit");
+    }
+
+    /**
+     * Test the minimum/maximum length
+     */
+    @Test
+    public void testLength() {
+        CodeValidator validator = new CodeValidator((String) null, -1, -1, (CheckDigit) null);
+        final String length_10 = "1234567890";
+        final String length_11 = "12345678901";
+        final String length_12 = "123456789012";
+        final String length_20 = "12345678901234567890";
+        final String length_21 = "123456789012345678901";
+        final String length_22 = "1234567890123456789012";
+
+        assertEquals(-1, validator.getMinLength(), "No min");
+        assertEquals(-1, validator.getMaxLength(), "No max");
+
+        assertEquals(length_10, validator.validate(length_10), "No Length 10");
+        assertEquals(length_11, validator.validate(length_11), "No Length 11");
+        assertEquals(length_12, validator.validate(length_12), "No Length 12");
+        assertEquals(length_20, validator.validate(length_20), "No Length 20");
+        assertEquals(length_21, validator.validate(length_21), "No Length 21");
+        assertEquals(length_22, validator.validate(length_22), "No Length 22");
+
+        validator = new CodeValidator((String) null, 11, -1, (CheckDigit) null);
+        assertEquals(11, validator.getMinLength(), "Min 11 - min");
+        assertEquals(-1, validator.getMaxLength(), "Min 11 - max");
+        assertNull(validator.validate(length_10), "Min 11 - 10");
+        assertEquals(length_11, validator.validate(length_11), "Min 11 - 11");
+        assertEquals(length_12, validator.validate(length_12), "Min 11 - 12");
+        assertEquals(length_20, validator.validate(length_20), "Min 11 - 20");
+        assertEquals(length_21, validator.validate(length_21), "Min 11 - 21");
+        assertEquals(length_22, validator.validate(length_22), "Min 11 - 22");
+
+        validator = new CodeValidator((String) null, -1, 21, (CheckDigit) null);
+        assertEquals(-1, validator.getMinLength(), "Max 21 - min");
+        assertEquals(21, validator.getMaxLength(), "Max 21 - max");
+        assertEquals(length_10, validator.validate(length_10), "Max 21 - 10");
+        assertEquals(length_11, validator.validate(length_11), "Max 21 - 11");
+        assertEquals(length_12, validator.validate(length_12), "Max 21 - 12");
+        assertEquals(length_20, validator.validate(length_20), "Max 21 - 20");
+        assertEquals(length_21, validator.validate(length_21), "Max 21 - 21");
+        assertNull(validator.validate(length_22), "Max 21 - 22");
+
+        validator = new CodeValidator((String) null, 11, 21, (CheckDigit) null);
+        assertEquals(11, validator.getMinLength(), "Min 11 / Max 21 - min");
+        assertEquals(21, validator.getMaxLength(), "Min 11 / Max 21 - max");
+        assertNull(validator.validate(length_10), "Min 11 / Max 21 - 10");
+        assertEquals(length_11, validator.validate(length_11), "Min 11 / Max 21 - 11");
+        assertEquals(length_12, validator.validate(length_12), "Min 11 / Max 21 - 12");
+        assertEquals(length_20, validator.validate(length_20), "Min 11 / Max 21 - 20");
+        assertEquals(length_21, validator.validate(length_21), "Min 11 / Max 21 - 21");
+        assertNull(validator.validate(length_22), "Min 11 / Max 21 - 22");
+
+        validator = new CodeValidator((String) null, 11, 11, (CheckDigit) null);
+        assertEquals(11, validator.getMinLength(), "Exact 11 - min");
+        assertEquals(11, validator.getMaxLength(), "Exact 11 - max");
+        assertNull(validator.validate(length_10), "Exact 11 - 10");
+        assertEquals(length_11, validator.validate(length_11), "Exact 11 - 11");
+        assertNull(validator.validate(length_12), "Exact 11 - 12");
+    }
+
+    /**
+     * Test Regular Expression.
+     */
+    @Test
+    public void testNoInput() {
+        final CodeValidator validator = new CodeValidator((String) null, -1, -1, (CheckDigit) null);
+        assertNull(validator.validate(null), "Null");
+        assertNull(validator.validate(""), "Zero Length");
+        assertNull(validator.validate("   "), "Spaces");
+        assertEquals(validator.validate(" A  "), "A", "Trimmed");
+    }
+
+    /**
+     * Test Regular Expression.
+     */
+    @Test
+    public void testRegex() {
+        CodeValidator validator = new CodeValidator((String) null, -1, -1, (CheckDigit) null);
+
+        final String value2 = "12";
+        final String value3 = "123";
+        final String value4 = "1234";
+        final String value5 = "12345";
+        final String invalid = "12a4";
+
+        // No Regular Expression
+        assertNull(validator.getRegexValidator(), "No Regex");
+        assertEquals(value2, validator.validate(value2), "No Regex 2");
+        assertEquals(value3, validator.validate(value3), "No Regex 3");
+        assertEquals(value4, validator.validate(value4), "No Regex 4");
+        assertEquals(value5, validator.validate(value5), "No Regex 5");
+        assertEquals(invalid, validator.validate(invalid), "No Regex invalid");
+
+        // Regular Expression
+        String regex = "^([0-9]{3,4})$";
+        validator = new CodeValidator(regex, -1, -1, (CheckDigit) null);
+        assertNotNull(validator.getRegexValidator(), "No Regex");
+        assertNull(validator.validate(value2), "Regex 2");
+        assertEquals(value3, validator.validate(value3), "Regex 3");
+        assertEquals(value4, validator.validate(value4), "Regex 4");
+        assertNull(validator.validate(value5), "Regex 5");
+        assertNull(validator.validate(invalid), "Regex invalid");
+
+        // Reformatted
+        regex = "^([0-9]{3})(?:[-\\s])([0-9]{3})$";
+        validator = new CodeValidator(new RegexValidator(regex), 6, (CheckDigit) null);
+        assertEquals(validator.validate("123-456"), "123456", "Reformat 123-456");
+        assertEquals(validator.validate("123 456"), "123456", "Reformat 123 456");
+        assertNull(validator.validate("123456"), "Reformat 123456");
+        assertNull(validator.validate("123.456"), "Reformat 123.456");
+
+        regex = "^(?:([0-9]{3})(?:[-\\s])([0-9]{3}))|([0-9]{6})$";
+        validator = new CodeValidator(new RegexValidator(regex), 6, (CheckDigit) null);
+        assertEquals(validator.getRegexValidator().toString(), "RegexValidator{" + regex + "}", "Reformat 2 Regex");
+        assertEquals(validator.validate("123-456"), "123456", "Reformat 2 123-456");
+        assertEquals(validator.validate("123 456"), "123456", "Reformat 2 123 456");
+        assertEquals(validator.validate("123456"), "123456", "Reformat 2 123456");
+
+    }
+
+    @Test
+    public void testValidator294_1() {
+        CodeValidator validator = new CodeValidator((String) null, 0, -1, (CheckDigit) null);
+        assertNull(validator.validate(null), "Null");
+        validator = new CodeValidator((String) null, -1, 0, (CheckDigit) null);
+        assertNull(validator.validate(null), "Null");
+    }
+
+    @Test
+    public void testValidator294_2() {
+        final CodeValidator validator = new CodeValidator((String) null, -1, 0, (CheckDigit) null);
+        assertNull(validator.validate(null), "Null");
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/CreditCardValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/CreditCardValidatorTest.java
index 60406e1..97380a4 100644
--- a/src/test/java/org/apache/commons/validator/routines/CreditCardValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/CreditCardValidatorTest.java
@@ -16,70 +16,343 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import org.apache.commons.validator.routines.CreditCardValidator.CreditCardRange;
 import org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit;
-
-import junit.framework.TestCase;
+import org.junit.jupiter.api.Test;
 
 /**
  * Test the CreditCardValidator class.
  */
-public class CreditCardValidatorTest extends TestCase {
+public class CreditCardValidatorTest {
 
-    private static final String VALID_VISA       = "4417123456789113"; // 16
-    private static final String ERROR_VISA       = "4417123456789112";
+    private static final String VALID_VISA = "4417123456789113"; // 16
+    private static final String ERROR_VISA = "4417123456789112";
     private static final String VALID_SHORT_VISA = "4222222222222"; // 13
     private static final String ERROR_SHORT_VISA = "4222222222229";
-    private static final String VALID_AMEX       = "378282246310005"; // 15
-    private static final String ERROR_AMEX       = "378282246310001";
+    private static final String VALID_AMEX = "378282246310005"; // 15
+    private static final String ERROR_AMEX = "378282246310001";
     private static final String VALID_MASTERCARD = "5105105105105100";
     private static final String ERROR_MASTERCARD = "5105105105105105";
-    private static final String VALID_DISCOVER   = "6011000990139424";
-    private static final String ERROR_DISCOVER   = "6011000990139421";
+    private static final String VALID_DISCOVER = "6011000990139424";
+    private static final String ERROR_DISCOVER = "6011000990139421";
     private static final String VALID_DISCOVER65 = "6534567890123458"; // FIXME need verified test data for Discover with "65" prefix
     private static final String ERROR_DISCOVER65 = "6534567890123450"; // FIXME need verified test data for Discover with "65" prefix
-    private static final String VALID_DINERS     = "30569309025904"; // 14
-    private static final String ERROR_DINERS     = "30569309025901";
-    private static final String VALID_VPAY       = "4370000000000061"; // 16
-    private static final String VALID_VPAY2      = "4370000000000012";
-    private static final String ERROR_VPAY       = "4370000000000069";
+    private static final String VALID_DINERS = "30569309025904"; // 14
+    private static final String ERROR_DINERS = "30569309025901";
+    private static final String VALID_VPAY = "4370000000000061"; // 16
+    private static final String VALID_VPAY2 = "4370000000000012";
+    private static final String ERROR_VPAY = "4370000000000069";
 
-    private static final String [] VALID_CARDS = {
-        VALID_VISA,
-        VALID_SHORT_VISA,
-        VALID_AMEX,
-        VALID_MASTERCARD,
-        VALID_DISCOVER,
-        VALID_DISCOVER65,
-        VALID_DINERS,
-        VALID_VPAY,
-        VALID_VPAY2,
-        "60115564485789458", // VALIDATOR-403
+    private static final String[] VALID_CARDS = { VALID_VISA, VALID_SHORT_VISA, VALID_AMEX, VALID_MASTERCARD, VALID_DISCOVER, VALID_DISCOVER65, VALID_DINERS,
+            VALID_VPAY, VALID_VPAY2, "60115564485789458", // VALIDATOR-403
     };
 
-    private static final String [] ERROR_CARDS = {
-        ERROR_VISA,
-        ERROR_SHORT_VISA,
-        ERROR_AMEX,
-        ERROR_MASTERCARD,
-        ERROR_DISCOVER,
-        ERROR_DISCOVER65,
-        ERROR_DINERS,
-        ERROR_VPAY,
+    private static final String[] ERROR_CARDS = { ERROR_VISA, ERROR_SHORT_VISA, ERROR_AMEX, ERROR_MASTERCARD, ERROR_DISCOVER, ERROR_DISCOVER65, ERROR_DINERS,
+            ERROR_VPAY,
 //        ERROR_VPAY2,
-        "",
-        "12345678901", // too short (11)
-        "12345678901234567890", // too long (20)
-        "4417123456789112", // invalid check digit
+            "", "12345678901", // too short (11)
+            "12345678901234567890", // too long (20)
+            "4417123456789112", // invalid check digit
     };
 
-    /**
-     * Constructor for CreditCardValidatorTest.
-     */
-    public CreditCardValidatorTest(final String name) {
-        super(name);
+    @Test
+    public void testAddAllowedCardType() {
+        final CreditCardValidator ccv = new CreditCardValidator(CreditCardValidator.NONE);
+        // Turned off all cards so even valid numbers should fail
+        assertFalse(ccv.isValid(VALID_VISA));
+        assertFalse(ccv.isValid(VALID_AMEX));
+        assertFalse(ccv.isValid(VALID_MASTERCARD));
+        assertFalse(ccv.isValid(VALID_DISCOVER));
+        assertFalse(ccv.isValid(VALID_DINERS));
     }
 
+    /**
+     * Test the Amex Card option
+     */
+    @Test
+    public void testAmexOption() {
+        final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.AMEX);
+        assertFalse(validator.isValid(ERROR_AMEX), "Invalid");
+        assertNull(validator.validate(ERROR_AMEX), "validate()");
+        assertEquals(VALID_AMEX, validator.validate(VALID_AMEX));
+
+        assertTrue(validator.isValid(VALID_AMEX), "Amex");
+        assertFalse(validator.isValid(VALID_DINERS), "Diners");
+        assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
+        assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
+        assertFalse(validator.isValid(VALID_VISA), "Visa");
+        assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
+    }
+
+    /**
+     * Test the Amex Card validator
+     */
+    @Test
+    public void testAmexValidator() {
+
+        final CodeValidator validator = CreditCardValidator.AMEX_VALIDATOR;
+        final RegexValidator regex = validator.getRegexValidator();
+
+        // ****** Test Regular Expression ******
+        // length 15 and start with a "34" or "37"
+        assertFalse(regex.isValid("343456789012"), "Length 12");
+        assertFalse(regex.isValid("3434567890123"), "Length 13");
+        assertFalse(regex.isValid("34345678901234"), "Length 14");
+        assertTrue(regex.isValid("343456789012345"), "Length 15");
+        assertFalse(regex.isValid("3434567890123456"), "Length 16");
+        assertFalse(regex.isValid("34345678901234567"), "Length 17");
+        assertFalse(regex.isValid("343456789012345678"), "Length 18");
+        assertFalse(regex.isValid("333456789012345"), "Prefix 33");
+        assertTrue(regex.isValid("343456789012345"), "Prefix 34");
+        assertFalse(regex.isValid("353456789012345"), "Prefix 35");
+        assertFalse(regex.isValid("363456789012345"), "Prefix 36");
+        assertTrue(regex.isValid("373456789012345"), "Prefix 37");
+        assertFalse(regex.isValid("383456789012345"), "Prefix 38");
+        assertFalse(regex.isValid("413456789012345"), "Prefix 41");
+        assertFalse(regex.isValid("3434567x9012345"), "Invalid Char");
+
+        // *********** Test Validator **********
+        assertTrue(regex.isValid(ERROR_AMEX), "Valid regex");
+        assertFalse(validator.isValid(ERROR_AMEX), "Invalid");
+        assertNull(validator.validate(ERROR_AMEX), "validate()");
+        assertEquals(VALID_AMEX, validator.validate(VALID_AMEX));
+
+        assertTrue(validator.isValid(VALID_AMEX), "Amex");
+        assertFalse(validator.isValid(VALID_DINERS), "Diners");
+        assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
+        assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
+        assertFalse(validator.isValid(VALID_VISA), "Visa");
+        assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
+
+        assertTrue(validator.isValid("371449635398431"), "Valid-A");
+        assertTrue(validator.isValid("340000000000009"), "Valid-B");
+        assertTrue(validator.isValid("370000000000002"), "Valid-C");
+        assertTrue(validator.isValid("378734493671000"), "Valid-D");
+    }
+
+    /**
+     * Test the CodeValidator array constructor
+     */
+    @Test
+    public void testArrayConstructor() {
+        final CreditCardValidator ccv = new CreditCardValidator(new CodeValidator[] { CreditCardValidator.VISA_VALIDATOR, CreditCardValidator.AMEX_VALIDATOR });
+
+        assertTrue(ccv.isValid(VALID_VISA));
+        assertTrue(ccv.isValid(VALID_SHORT_VISA));
+        assertTrue(ccv.isValid(VALID_AMEX));
+        assertFalse(ccv.isValid(VALID_MASTERCARD));
+        assertFalse(ccv.isValid(VALID_DISCOVER));
+
+        assertFalse(ccv.isValid(ERROR_VISA));
+        assertFalse(ccv.isValid(ERROR_SHORT_VISA));
+        assertFalse(ccv.isValid(ERROR_AMEX));
+        assertFalse(ccv.isValid(ERROR_MASTERCARD));
+        assertFalse(ccv.isValid(ERROR_DISCOVER));
+
+        try {
+            new CreditCardValidator((CodeValidator[]) null);
+            fail("Expected IllegalArgumentException");
+        } catch (final IllegalArgumentException iae) {
+            // expected result
+        }
+    }
+
+    /**
+     * Test the Diners Card option
+     */
+    @Test
+    public void testDinersOption() {
+        final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.DINERS);
+        assertFalse(validator.isValid(ERROR_DINERS), "Invalid");
+        assertNull(validator.validate(ERROR_DINERS), "validate()");
+        assertEquals(VALID_DINERS, validator.validate(VALID_DINERS));
+
+        assertFalse(validator.isValid(VALID_AMEX), "Amex");
+        assertTrue(validator.isValid(VALID_DINERS), "Diners");
+        assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
+        assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
+        assertFalse(validator.isValid(VALID_VISA), "Visa");
+        assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
+    }
+
+    /**
+     * Test the Diners Card validator
+     */
+    @Test
+    public void testDinersValidator() {
+
+        final CodeValidator validator = CreditCardValidator.DINERS_VALIDATOR;
+        final RegexValidator regex = validator.getRegexValidator();
+
+        // ****** Test Regular Expression ******
+        // length 14 and start with a "300-305" or "3095" or "36" or "38" or "39"
+        assertFalse(regex.isValid("300456789012"), "Length 12-300");
+        assertFalse(regex.isValid("363456789012"), "Length 12-36");
+        assertFalse(regex.isValid("3004567890123"), "Length 13-300");
+        assertFalse(regex.isValid("3634567890123"), "Length 13-36");
+        assertTrue(regex.isValid("30045678901234"), "Length 14-300");
+        assertTrue(regex.isValid("36345678901234"), "Length 14-36");
+        assertFalse(regex.isValid("300456789012345"), "Length 15-300");
+        assertFalse(regex.isValid("363456789012345"), "Length 15-36");
+        assertFalse(regex.isValid("3004567890123456"), "Length 16-300");
+        assertFalse(regex.isValid("3634567890123456"), "Length 16-36");
+        assertFalse(regex.isValid("30045678901234567"), "Length 17-300");
+        assertFalse(regex.isValid("36345678901234567"), "Length 17-36");
+        assertFalse(regex.isValid("300456789012345678"), "Length 18-300");
+        assertFalse(regex.isValid("363456789012345678"), "Length 18-36");
+
+        assertTrue(regex.isValid("30045678901234"), "Prefix 300");
+        assertTrue(regex.isValid("30145678901234"), "Prefix 301");
+        assertTrue(regex.isValid("30245678901234"), "Prefix 302");
+        assertTrue(regex.isValid("30345678901234"), "Prefix 303");
+        assertTrue(regex.isValid("30445678901234"), "Prefix 304");
+        assertTrue(regex.isValid("30545678901234"), "Prefix 305");
+        assertFalse(regex.isValid("30645678901234"), "Prefix 306");
+        assertFalse(regex.isValid("30945678901234"), "Prefix 3094");
+        assertTrue(regex.isValid("30955678901234"), "Prefix 3095");
+        assertFalse(regex.isValid("30965678901234"), "Prefix 3096");
+        assertFalse(regex.isValid("35345678901234"), "Prefix 35");
+        assertTrue(regex.isValid("36345678901234"), "Prefix 36");
+        assertFalse(regex.isValid("37345678901234"), "Prefix 37");
+        assertTrue(regex.isValid("38345678901234"), "Prefix 38");
+        assertTrue(regex.isValid("39345678901234"), "Prefix 39");
+
+        assertFalse(regex.isValid("3004567x901234"), "Invalid Char-A");
+        assertFalse(regex.isValid("3634567x901234"), "Invalid Char-B");
+
+        // *********** Test Validator **********
+        assertTrue(regex.isValid(ERROR_DINERS), "Valid regex");
+        assertFalse(validator.isValid(ERROR_DINERS), "Invalid");
+        assertNull(validator.validate(ERROR_DINERS), "validate()");
+        assertEquals(VALID_DINERS, validator.validate(VALID_DINERS));
+
+        assertFalse(validator.isValid(VALID_AMEX), "Amex");
+        assertTrue(validator.isValid(VALID_DINERS), "Diners");
+        assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
+        assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
+        assertFalse(validator.isValid(VALID_VISA), "Visa");
+        assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
+
+        assertTrue(validator.isValid("30000000000004"), "Valid-A");
+        assertTrue(validator.isValid("30123456789019"), "Valid-B");
+        assertTrue(validator.isValid("36432685260294"), "Valid-C");
+
+    }
+
+    /**
+     * Test the Discover Card option
+     */
+    @Test
+    public void testDiscoverOption() {
+        final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.DISCOVER);
+        assertFalse(validator.isValid(ERROR_DISCOVER), "Invalid");
+        assertFalse(validator.isValid(ERROR_DISCOVER65), "Invalid65");
+        assertNull(validator.validate(ERROR_DISCOVER), "validate()");
+        assertEquals(VALID_DISCOVER, validator.validate(VALID_DISCOVER));
+        assertEquals(VALID_DISCOVER65, validator.validate(VALID_DISCOVER65));
+
+        assertFalse(validator.isValid(VALID_AMEX), "Amex");
+        assertFalse(validator.isValid(VALID_DINERS), "Diners");
+        assertTrue(validator.isValid(VALID_DISCOVER), "Discover");
+        assertTrue(validator.isValid(VALID_DISCOVER65), "Discover");
+        assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
+        assertFalse(validator.isValid(VALID_VISA), "Visa");
+        assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
+    }
+
+    /**
+     * Test the Discover Card validator
+     */
+    @Test
+    public void testDiscoverValidator() {
+
+        final CodeValidator validator = CreditCardValidator.DISCOVER_VALIDATOR;
+        final RegexValidator regex = validator.getRegexValidator();
+
+        // ****** Test Regular Expression ******
+        // length 16 and start with either "6011" or or "64[4-9]" or "65"
+        assertFalse(regex.isValid("601156789012"), "Length 12-6011");
+        assertFalse(regex.isValid("653456789012"), "Length 12-65");
+        assertFalse(regex.isValid("6011567890123"), "Length 13-6011");
+        assertFalse(regex.isValid("6534567890123"), "Length 13-65");
+        assertFalse(regex.isValid("60115678901234"), "Length 14-6011");
+        assertFalse(regex.isValid("65345678901234"), "Length 14-65");
+        assertFalse(regex.isValid("601156789012345"), "Length 15-6011");
+        assertFalse(regex.isValid("653456789012345"), "Length 15-65");
+        assertTrue(regex.isValid("6011567890123456"), "Length 16-6011");
+        assertTrue(regex.isValid("6444567890123456"), "Length 16-644");
+        assertTrue(regex.isValid("6484567890123456"), "Length 16-648");
+        assertTrue(regex.isValid("6534567890123456"), "Length 16-65");
+        assertFalse(regex.isValid("65345678901234567"), "Length 17-65");
+        assertFalse(regex.isValid("601156789012345678"), "Length 18-6011");
+        assertFalse(regex.isValid("653456789012345678"), "Length 18-65");
+
+        assertFalse(regex.isValid("6404567890123456"), "Prefix 640");
+        assertFalse(regex.isValid("6414567890123456"), "Prefix 641");
+        assertFalse(regex.isValid("6424567890123456"), "Prefix 642");
+        assertFalse(regex.isValid("6434567890123456"), "Prefix 643");
+        assertFalse(regex.isValid("6010567890123456"), "Prefix 6010");
+        assertFalse(regex.isValid("6012567890123456"), "Prefix 6012");
+        assertFalse(regex.isValid("6011567x90123456"), "Invalid Char");
+
+        // *********** Test Validator **********
+        assertTrue(regex.isValid(ERROR_DISCOVER), "Valid regex");
+        assertTrue(regex.isValid(ERROR_DISCOVER65), "Valid regex65");
+        assertFalse(validator.isValid(ERROR_DISCOVER), "Invalid");
+        assertFalse(validator.isValid(ERROR_DISCOVER65), "Invalid65");
+        assertNull(validator.validate(ERROR_DISCOVER), "validate()");
+        assertEquals(VALID_DISCOVER, validator.validate(VALID_DISCOVER));
+        assertEquals(VALID_DISCOVER65, validator.validate(VALID_DISCOVER65));
+
+        assertFalse(validator.isValid(VALID_AMEX), "Amex");
+        assertFalse(validator.isValid(VALID_DINERS), "Diners");
+        assertTrue(validator.isValid(VALID_DISCOVER), "Discover");
+        assertTrue(validator.isValid(VALID_DISCOVER65), "Discover");
+        assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
+        assertFalse(validator.isValid(VALID_VISA), "Visa");
+        assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
+
+        assertTrue(validator.isValid("6011111111111117"), "Valid-A");
+        assertTrue(validator.isValid("6011000000000004"), "Valid-B");
+        assertTrue(validator.isValid("6011000000000012"), "Valid-C");
+
+    }
+
+    @Test
+    public void testDisjointRange() {
+        CreditCardValidator ccv = new CreditCardValidator(new CreditCardRange[] { new CreditCardRange("305", "4", new int[] { 13, 16 }), });
+        assertEquals(13, VALID_SHORT_VISA.length());
+        assertEquals(16, VALID_VISA.length());
+        assertEquals(14, VALID_DINERS.length());
+        assertTrue(ccv.isValid(VALID_SHORT_VISA));
+        assertTrue(ccv.isValid(VALID_VISA));
+        assertFalse(ccv.isValid(ERROR_SHORT_VISA));
+        assertFalse(ccv.isValid(ERROR_VISA));
+        assertFalse(ccv.isValid(VALID_DINERS));
+        ccv = new CreditCardValidator(new CreditCardRange[] {
+                // add 14 as a valid length
+                new CreditCardRange("305", "4", new int[] { 13, 14, 16 }), });
+        assertTrue(ccv.isValid(VALID_DINERS));
+    }
+
+    @Test
+    public void testGeneric() {
+        final CreditCardValidator ccv = CreditCardValidator.genericCreditCardValidator();
+        for (final String s : VALID_CARDS) {
+            assertTrue(ccv.isValid(s), s);
+        }
+        for (final String s : ERROR_CARDS) {
+            assertFalse(ccv.isValid(s), s);
+        }
+    }
+
+    @Test
     public void testIsValid() {
         CreditCardValidator ccv = new CreditCardValidator();
 
@@ -87,8 +360,8 @@
 
         assertFalse(ccv.isValid(null));
         assertFalse(ccv.isValid(""));
-        assertFalse(ccv.isValid("123456789012"));   // too short
-        assertFalse(ccv.isValid("12345678901234567890"));   // too long
+        assertFalse(ccv.isValid("123456789012")); // too short
+        assertFalse(ccv.isValid("12345678901234567890")); // too long
         assertFalse(ccv.isValid("4417123456789112"));
         assertFalse(ccv.isValid("4417q23456w89113"));
         assertTrue(ccv.isValid(VALID_VISA));
@@ -110,463 +383,138 @@
         assertFalse(ccv.isValid("4417123456789113"));
     }
 
-    public void testAddAllowedCardType() {
-        final CreditCardValidator ccv = new CreditCardValidator(CreditCardValidator.NONE);
-        // Turned off all cards so even valid numbers should fail
-        assertFalse(ccv.isValid(VALID_VISA));
-        assertFalse(ccv.isValid(VALID_AMEX));
-        assertFalse(ccv.isValid(VALID_MASTERCARD));
-        assertFalse(ccv.isValid(VALID_DISCOVER));
-        assertFalse(ccv.isValid(VALID_DINERS));
-    }
-
-    /**
-     * Test the CodeValidator array constructor
-     */
-    public void testArrayConstructor() {
-        final CreditCardValidator ccv = new CreditCardValidator(new CodeValidator[]
-               {CreditCardValidator.VISA_VALIDATOR, CreditCardValidator.AMEX_VALIDATOR});
-
-        assertTrue(ccv.isValid(VALID_VISA));
-        assertTrue(ccv.isValid(VALID_SHORT_VISA));
-        assertTrue(ccv.isValid(VALID_AMEX));
-        assertFalse(ccv.isValid(VALID_MASTERCARD));
-        assertFalse(ccv.isValid(VALID_DISCOVER));
-
-        assertFalse(ccv.isValid(ERROR_VISA));
-        assertFalse(ccv.isValid(ERROR_SHORT_VISA));
-        assertFalse(ccv.isValid(ERROR_AMEX));
-        assertFalse(ccv.isValid(ERROR_MASTERCARD));
-        assertFalse(ccv.isValid(ERROR_DISCOVER));
-
-        try {
-            new CreditCardValidator((CodeValidator[]) null);
-            fail("Expected IllegalArgumentException");
-        } catch(final IllegalArgumentException iae) {
-            // expected result
-        }
-    }
-
-    /**
-     * Test the Amex Card validator
-     */
-    public void testAmexValidator() {
-
-        final CodeValidator validator = CreditCardValidator.AMEX_VALIDATOR;
-        final RegexValidator regex    = validator.getRegexValidator();
-
-        // ****** Test Regular Expression ******
-        // length 15 and start with a "34" or "37"
-        assertFalse("Length 12",      regex.isValid("343456789012"));
-        assertFalse("Length 13",      regex.isValid("3434567890123"));
-        assertFalse("Length 14",      regex.isValid("34345678901234"));
-        assertTrue("Length 15",       regex.isValid("343456789012345"));
-        assertFalse("Length 16",      regex.isValid("3434567890123456"));
-        assertFalse("Length 17",      regex.isValid("34345678901234567"));
-        assertFalse("Length 18",      regex.isValid("343456789012345678"));
-        assertFalse("Prefix 33",      regex.isValid("333456789012345"));
-        assertTrue("Prefix 34",       regex.isValid("343456789012345"));
-        assertFalse("Prefix 35",      regex.isValid("353456789012345"));
-        assertFalse("Prefix 36",      regex.isValid("363456789012345"));
-        assertTrue("Prefix 37",       regex.isValid("373456789012345"));
-        assertFalse("Prefix 38",      regex.isValid("383456789012345"));
-        assertFalse("Prefix 41",      regex.isValid("413456789012345"));
-        assertFalse("Invalid Char",   regex.isValid("3434567x9012345"));
-
-        // *********** Test Validator **********
-        assertTrue("Valid regex",     regex.isValid(ERROR_AMEX));
-        assertFalse("Invalid",        validator.isValid(ERROR_AMEX));
-        assertNull("validate()",      validator.validate(ERROR_AMEX));
-        assertEquals(VALID_AMEX,      validator.validate(VALID_AMEX));
-
-        assertTrue("Amex",            validator.isValid(VALID_AMEX));
-        assertFalse("Diners",         validator.isValid(VALID_DINERS));
-        assertFalse("Discover",       validator.isValid(VALID_DISCOVER));
-        assertFalse("Mastercard",     validator.isValid(VALID_MASTERCARD));
-        assertFalse("Visa",           validator.isValid(VALID_VISA));
-        assertFalse("Visa Short",     validator.isValid(VALID_SHORT_VISA));
-
-        assertTrue("Valid-A",         validator.isValid("371449635398431"));
-        assertTrue("Valid-B",         validator.isValid("340000000000009"));
-        assertTrue("Valid-C",         validator.isValid("370000000000002"));
-        assertTrue("Valid-D",         validator.isValid("378734493671000"));
-    }
-
-    /**
-     * Test the Amex Card option
-     */
-    public void testAmexOption() {
-        final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.AMEX);
-        assertFalse("Invalid",        validator.isValid(ERROR_AMEX));
-        assertNull("validate()",      validator.validate(ERROR_AMEX));
-        assertEquals(VALID_AMEX,      validator.validate(VALID_AMEX));
-
-        assertTrue("Amex",            validator.isValid(VALID_AMEX));
-        assertFalse("Diners",         validator.isValid(VALID_DINERS));
-        assertFalse("Discover",       validator.isValid(VALID_DISCOVER));
-        assertFalse("Mastercard",     validator.isValid(VALID_MASTERCARD));
-        assertFalse("Visa",           validator.isValid(VALID_VISA));
-        assertFalse("Visa Short",     validator.isValid(VALID_SHORT_VISA));
-    }
-
-    /**
-     * Test the Diners Card validator
-     */
-    public void testDinersValidator() {
-
-        final CodeValidator validator = CreditCardValidator.DINERS_VALIDATOR;
-        final RegexValidator regex    = validator.getRegexValidator();
-
-        // ****** Test Regular Expression ******
-        // length 14 and start with a "300-305" or "3095" or "36" or "38" or "39"
-        assertFalse("Length 12-300",  regex.isValid("300456789012"));
-        assertFalse("Length 12-36",   regex.isValid("363456789012"));
-        assertFalse("Length 13-300",  regex.isValid("3004567890123"));
-        assertFalse("Length 13-36",   regex.isValid("3634567890123"));
-        assertTrue("Length 14-300",   regex.isValid("30045678901234"));
-        assertTrue("Length 14-36",    regex.isValid("36345678901234"));
-        assertFalse("Length 15-300",  regex.isValid("300456789012345"));
-        assertFalse("Length 15-36",   regex.isValid("363456789012345"));
-        assertFalse("Length 16-300",  regex.isValid("3004567890123456"));
-        assertFalse("Length 16-36",   regex.isValid("3634567890123456"));
-        assertFalse("Length 17-300",  regex.isValid("30045678901234567"));
-        assertFalse("Length 17-36",   regex.isValid("36345678901234567"));
-        assertFalse("Length 18-300",  regex.isValid("300456789012345678"));
-        assertFalse("Length 18-36",   regex.isValid("363456789012345678"));
-
-        assertTrue("Prefix 300",      regex.isValid("30045678901234"));
-        assertTrue("Prefix 301",      regex.isValid("30145678901234"));
-        assertTrue("Prefix 302",      regex.isValid("30245678901234"));
-        assertTrue("Prefix 303",      regex.isValid("30345678901234"));
-        assertTrue("Prefix 304",      regex.isValid("30445678901234"));
-        assertTrue("Prefix 305",      regex.isValid("30545678901234"));
-        assertFalse("Prefix 306",     regex.isValid("30645678901234"));
-        assertFalse("Prefix 3094",    regex.isValid("30945678901234"));
-        assertTrue( "Prefix 3095",    regex.isValid("30955678901234"));
-        assertFalse("Prefix 3096",    regex.isValid("30965678901234"));
-        assertFalse("Prefix 35",      regex.isValid("35345678901234"));
-        assertTrue("Prefix 36",       regex.isValid("36345678901234"));
-        assertFalse("Prefix 37",      regex.isValid("37345678901234"));
-        assertTrue("Prefix 38",       regex.isValid("38345678901234"));
-        assertTrue("Prefix 39",       regex.isValid("39345678901234"));
-
-        assertFalse("Invalid Char-A", regex.isValid("3004567x901234"));
-        assertFalse("Invalid Char-B", regex.isValid("3634567x901234"));
-
-        // *********** Test Validator **********
-        assertTrue("Valid regex",     regex.isValid(ERROR_DINERS));
-        assertFalse("Invalid",        validator.isValid(ERROR_DINERS));
-        assertNull("validate()",      validator.validate(ERROR_DINERS));
-        assertEquals(VALID_DINERS,    validator.validate(VALID_DINERS));
-
-        assertFalse("Amex",           validator.isValid(VALID_AMEX));
-        assertTrue("Diners",          validator.isValid(VALID_DINERS));
-        assertFalse("Discover",       validator.isValid(VALID_DISCOVER));
-        assertFalse("Mastercard",     validator.isValid(VALID_MASTERCARD));
-        assertFalse("Visa",           validator.isValid(VALID_VISA));
-        assertFalse("Visa Short",     validator.isValid(VALID_SHORT_VISA));
-
-        assertTrue("Valid-A",         validator.isValid("30000000000004"));
-        assertTrue("Valid-B",         validator.isValid("30123456789019"));
-        assertTrue("Valid-C",         validator.isValid("36432685260294"));
-
-    }
-
-    /**
-     * Test the Diners Card option
-     */
-    public void testDinersOption() {
-        final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.DINERS);
-        assertFalse("Invalid",        validator.isValid(ERROR_DINERS));
-        assertNull("validate()",      validator.validate(ERROR_DINERS));
-        assertEquals(VALID_DINERS,    validator.validate(VALID_DINERS));
-
-        assertFalse("Amex",           validator.isValid(VALID_AMEX));
-        assertTrue("Diners",          validator.isValid(VALID_DINERS));
-        assertFalse("Discover",       validator.isValid(VALID_DISCOVER));
-        assertFalse("Mastercard",     validator.isValid(VALID_MASTERCARD));
-        assertFalse("Visa",           validator.isValid(VALID_VISA));
-        assertFalse("Visa Short",     validator.isValid(VALID_SHORT_VISA));
-    }
-
-    /**
-     * Test the Discover Card validator
-     */
-    public void testDiscoverValidator() {
-
-        final CodeValidator validator = CreditCardValidator.DISCOVER_VALIDATOR;
-        final RegexValidator regex    = validator.getRegexValidator();
-
-        // ****** Test Regular Expression ******
-        // length 16 and start with either "6011" or or "64[4-9]" or "65"
-        assertFalse("Length 12-6011", regex.isValid("601156789012"));
-        assertFalse("Length 12-65",   regex.isValid("653456789012"));
-        assertFalse("Length 13-6011", regex.isValid("6011567890123"));
-        assertFalse("Length 13-65",   regex.isValid("6534567890123"));
-        assertFalse("Length 14-6011", regex.isValid("60115678901234"));
-        assertFalse("Length 14-65",   regex.isValid("65345678901234"));
-        assertFalse("Length 15-6011", regex.isValid("601156789012345"));
-        assertFalse("Length 15-65",   regex.isValid("653456789012345"));
-        assertTrue("Length 16-6011",  regex.isValid("6011567890123456"));
-        assertTrue("Length 16-644",   regex.isValid("6444567890123456"));
-        assertTrue("Length 16-648",   regex.isValid("6484567890123456"));
-        assertTrue("Length 16-65",    regex.isValid("6534567890123456"));
-        assertFalse("Length 17-65",   regex.isValid("65345678901234567"));
-        assertFalse("Length 18-6011", regex.isValid("601156789012345678"));
-        assertFalse("Length 18-65",   regex.isValid("653456789012345678"));
-
-        assertFalse("Prefix 640",     regex.isValid("6404567890123456"));
-        assertFalse("Prefix 641",     regex.isValid("6414567890123456"));
-        assertFalse("Prefix 642",     regex.isValid("6424567890123456"));
-        assertFalse("Prefix 643",     regex.isValid("6434567890123456"));
-        assertFalse("Prefix 6010",    regex.isValid("6010567890123456"));
-        assertFalse("Prefix 6012",    regex.isValid("6012567890123456"));
-        assertFalse("Invalid Char",   regex.isValid("6011567x90123456"));
-
-        // *********** Test Validator **********
-        assertTrue("Valid regex",     regex.isValid(ERROR_DISCOVER));
-        assertTrue("Valid regex65",   regex.isValid(ERROR_DISCOVER65));
-        assertFalse("Invalid",        validator.isValid(ERROR_DISCOVER));
-        assertFalse("Invalid65",      validator.isValid(ERROR_DISCOVER65));
-        assertNull("validate()",      validator.validate(ERROR_DISCOVER));
-        assertEquals(VALID_DISCOVER,  validator.validate(VALID_DISCOVER));
-        assertEquals(VALID_DISCOVER65, validator.validate(VALID_DISCOVER65));
-
-        assertFalse("Amex",           validator.isValid(VALID_AMEX));
-        assertFalse("Diners",         validator.isValid(VALID_DINERS));
-        assertTrue("Discover",        validator.isValid(VALID_DISCOVER));
-        assertTrue("Discover",        validator.isValid(VALID_DISCOVER65));
-        assertFalse("Mastercard",     validator.isValid(VALID_MASTERCARD));
-        assertFalse("Visa",           validator.isValid(VALID_VISA));
-        assertFalse("Visa Short",     validator.isValid(VALID_SHORT_VISA));
-
-        assertTrue("Valid-A",         validator.isValid("6011111111111117"));
-        assertTrue("Valid-B",         validator.isValid("6011000000000004"));
-        assertTrue("Valid-C",         validator.isValid("6011000000000012"));
-
-    }
-
-    /**
-     * Test the Discover Card option
-     */
-    public void testDiscoverOption() {
-        final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.DISCOVER);
-        assertFalse("Invalid",        validator.isValid(ERROR_DISCOVER));
-        assertFalse("Invalid65",      validator.isValid(ERROR_DISCOVER65));
-        assertNull("validate()",      validator.validate(ERROR_DISCOVER));
-        assertEquals(VALID_DISCOVER,  validator.validate(VALID_DISCOVER));
-        assertEquals(VALID_DISCOVER65, validator.validate(VALID_DISCOVER65));
-
-        assertFalse("Amex",           validator.isValid(VALID_AMEX));
-        assertFalse("Diners",         validator.isValid(VALID_DINERS));
-        assertTrue("Discover",        validator.isValid(VALID_DISCOVER));
-        assertTrue("Discover",        validator.isValid(VALID_DISCOVER65));
-        assertFalse("Mastercard",     validator.isValid(VALID_MASTERCARD));
-        assertFalse("Visa",           validator.isValid(VALID_VISA));
-        assertFalse("Visa Short",     validator.isValid(VALID_SHORT_VISA));
-    }
-
-    /**
-     * Test the Mastercard Card validator
-     */
-    public void testMastercardValidator() {
-
-        final CodeValidator validator = CreditCardValidator.MASTERCARD_VALIDATOR;
-        final RegexValidator regex    = validator.getRegexValidator();
-
-        // ****** Test Regular Expression ******
-        // length 16 and start with a "51-55"
-        assertFalse("Length 12",      regex.isValid("513456789012"));
-        assertFalse("Length 13",      regex.isValid("5134567890123"));
-        assertFalse("Length 14",      regex.isValid("51345678901234"));
-        assertFalse("Length 15",      regex.isValid("513456789012345"));
-        assertTrue("Length 16",       regex.isValid("5134567890123456"));
-        assertFalse("Length 17",      regex.isValid("51345678901234567"));
-        assertFalse("Length 18",      regex.isValid("513456789012345678"));
-        assertFalse("Prefix 41",      regex.isValid("4134567890123456"));
-        assertFalse("Prefix 50",      regex.isValid("5034567890123456"));
-        assertTrue("Prefix 51",       regex.isValid("5134567890123456"));
-        assertTrue("Prefix 52",       regex.isValid("5234567890123456"));
-        assertTrue("Prefix 53",       regex.isValid("5334567890123456"));
-        assertTrue("Prefix 54",       regex.isValid("5434567890123456"));
-        assertTrue("Prefix 55",       regex.isValid("5534567890123456"));
-        assertFalse("Prefix 56",      regex.isValid("5634567890123456"));
-        assertFalse("Prefix 61",      regex.isValid("6134567890123456"));
-        assertFalse("Invalid Char",   regex.isValid("5134567x90123456"));
-
-        // *********** Test Validator **********
-        assertTrue("Valid regex",     regex.isValid(ERROR_MASTERCARD));
-        assertFalse("Invalid",        validator.isValid(ERROR_MASTERCARD));
-        assertNull("validate()",      validator.validate(ERROR_MASTERCARD));
-        assertEquals(VALID_MASTERCARD, validator.validate(VALID_MASTERCARD));
-
-        assertFalse("Amex",           validator.isValid(VALID_AMEX));
-        assertFalse("Diners",         validator.isValid(VALID_DINERS));
-        assertFalse("Discover",       validator.isValid(VALID_DISCOVER));
-        assertTrue("Mastercard",      validator.isValid(VALID_MASTERCARD));
-        assertFalse("Visa",           validator.isValid(VALID_VISA));
-        assertFalse("Visa Short",     validator.isValid(VALID_SHORT_VISA));
-
-        assertTrue("Valid-A",         validator.isValid("5500000000000004"));
-        assertTrue("Valid-B",         validator.isValid("5424000000000015"));
-        assertTrue("Valid-C",         validator.isValid("5301250070000191"));
-        assertTrue("Valid-D",         validator.isValid("5123456789012346"));
-        assertTrue("Valid-E",         validator.isValid("5555555555554444"));
-
-        final RegexValidator rev = validator.getRegexValidator();
-        final String PAD = "0000000000";
-        assertFalse("222099",rev.isValid("222099"+PAD));
-        for(int i=222100; i <= 272099; i++) {
-            final String j = Integer.toString(i)+PAD;
-            assertTrue(j, rev.isValid(j));
-        }
-        assertFalse("272100",rev.isValid("272100"+PAD));
-    }
-
     /**
      * Test the Mastercard Card option
      */
+    @Test
     public void testMastercardOption() {
         final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.MASTERCARD);
-        assertFalse("Invalid",        validator.isValid(ERROR_MASTERCARD));
-        assertNull("validate()",      validator.validate(ERROR_MASTERCARD));
+        assertFalse(validator.isValid(ERROR_MASTERCARD), "Invalid");
+        assertNull(validator.validate(ERROR_MASTERCARD), "validate()");
         assertEquals(VALID_MASTERCARD, validator.validate(VALID_MASTERCARD));
 
-        assertFalse("Amex",           validator.isValid(VALID_AMEX));
-        assertFalse("Diners",         validator.isValid(VALID_DINERS));
-        assertFalse("Discover",       validator.isValid(VALID_DISCOVER));
-        assertTrue("Mastercard",      validator.isValid(VALID_MASTERCARD));
-        assertFalse("Visa",           validator.isValid(VALID_VISA));
-        assertFalse("Visa Short",     validator.isValid(VALID_SHORT_VISA));
-    }
-
-    /**
-     * Test the Visa Card validator
-     */
-    public void testVisaValidator() {
-
-        final CodeValidator validator = CreditCardValidator.VISA_VALIDATOR;
-        final RegexValidator regex    = validator.getRegexValidator();
-
-        // ****** Test Regular Expression ******
-        // length 13 or 16, must start with a "4"
-        assertFalse("Length 12",      regex.isValid("423456789012"));
-        assertTrue("Length 13",       regex.isValid("4234567890123"));
-        assertFalse("Length 14",      regex.isValid("42345678901234"));
-        assertFalse("Length 15",      regex.isValid("423456789012345"));
-        assertTrue("Length 16",       regex.isValid("4234567890123456"));
-        assertFalse("Length 17",      regex.isValid("42345678901234567"));
-        assertFalse("Length 18",      regex.isValid("423456789012345678"));
-        assertFalse("Invalid Pref-A", regex.isValid("3234567890123"));
-        assertFalse("Invalid Pref-B", regex.isValid("3234567890123456"));
-        assertFalse("Invalid Char-A", regex.isValid("4234567x90123"));
-        assertFalse("Invalid Char-B", regex.isValid("4234567x90123456"));
-
-        // *********** Test Validator **********
-        assertTrue("Valid regex",     regex.isValid(ERROR_VISA));
-        assertTrue("Valid regex-S",   regex.isValid(ERROR_SHORT_VISA));
-        assertFalse("Invalid",        validator.isValid(ERROR_VISA));
-        assertFalse("Invalid-S",      validator.isValid(ERROR_SHORT_VISA));
-        assertNull("validate()",      validator.validate(ERROR_VISA));
-        assertEquals(VALID_VISA,      validator.validate(VALID_VISA));
-        assertEquals(VALID_SHORT_VISA, validator.validate(VALID_SHORT_VISA));
-
-        assertFalse("Amex",           validator.isValid(VALID_AMEX));
-        assertFalse("Diners",         validator.isValid(VALID_DINERS));
-        assertFalse("Discover",       validator.isValid(VALID_DISCOVER));
-        assertFalse("Mastercard",     validator.isValid(VALID_MASTERCARD));
-        assertTrue("Visa",            validator.isValid(VALID_VISA));
-        assertTrue("Visa Short",      validator.isValid(VALID_SHORT_VISA));
-
-        assertTrue("Valid-A",         validator.isValid("4111111111111111"));
-        assertTrue("Valid-C",         validator.isValid("4543059999999982"));
-        assertTrue("Valid-B",         validator.isValid("4462000000000003"));
-        assertTrue("Valid-D",         validator.isValid("4508750000000009")); // Electron
-        assertTrue("Valid-E",         validator.isValid("4012888888881881"));
-    }
-
-    /**
-     * Test the Visa Card option
-     */
-    public void testVisaOption() {
-        final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.VISA);
-        assertFalse("Invalid",        validator.isValid(ERROR_VISA));
-        assertFalse("Invalid-S",      validator.isValid(ERROR_SHORT_VISA));
-        assertNull("validate()",      validator.validate(ERROR_VISA));
-        assertEquals(VALID_VISA,      validator.validate(VALID_VISA));
-        assertEquals(VALID_SHORT_VISA, validator.validate(VALID_SHORT_VISA));
-
-        assertFalse("Amex",           validator.isValid(VALID_AMEX));
-        assertFalse("Diners",         validator.isValid(VALID_DINERS));
-        assertFalse("Discover",       validator.isValid(VALID_DISCOVER));
-        assertFalse("Mastercard",     validator.isValid(VALID_MASTERCARD));
-        assertTrue("Visa",            validator.isValid(VALID_VISA));
-        assertTrue("Visa Short",      validator.isValid(VALID_SHORT_VISA));
-    }
-
-    public void testVPayOption() {
-        final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.VPAY);
-        assertTrue("Valid",           validator.isValid(VALID_VPAY));
-        assertTrue("Valid",           validator.isValid(VALID_VPAY2));
-        assertFalse("Invalid",        validator.isValid(ERROR_VPAY));
-        assertEquals(VALID_VPAY,      validator.validate(VALID_VPAY));
-        assertEquals(VALID_VPAY2,      validator.validate(VALID_VPAY2));
-
-        assertFalse("Amex",           validator.isValid(VALID_AMEX));
-        assertFalse("Diners",         validator.isValid(VALID_DINERS));
-        assertFalse("Discover",       validator.isValid(VALID_DISCOVER));
-        assertFalse("Mastercard",     validator.isValid(VALID_MASTERCARD));
-        assertTrue("Visa",            validator.isValid(VALID_VISA));
-        assertTrue("Visa Short",      validator.isValid(VALID_SHORT_VISA));
+        assertFalse(validator.isValid(VALID_AMEX), "Amex");
+        assertFalse(validator.isValid(VALID_DINERS), "Diners");
+        assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
+        assertTrue(validator.isValid(VALID_MASTERCARD), "Mastercard");
+        assertFalse(validator.isValid(VALID_VISA), "Visa");
+        assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
     }
 
     /**
      * Test using separators
      */
+    @Test
     public void testMastercardUsingSeparators() {
 
         final String MASTERCARD_REGEX_SEP = "^(5[1-5]\\d{2})(?:[- ])?(\\d{4})(?:[- ])?(\\d{4})(?:[- ])?(\\d{4})$";
         final CodeValidator validator = new CodeValidator(MASTERCARD_REGEX_SEP, LuhnCheckDigit.LUHN_CHECK_DIGIT);
-        final RegexValidator regex    = validator.getRegexValidator();
+        final RegexValidator regex = validator.getRegexValidator();
 
         // ****** Test Regular Expression ******
         // length 16 and start with a "51-55"
-        assertEquals("Number",  "5134567890123456", regex.validate("5134567890123456"));
-        assertEquals("Hyphen",  "5134567890123456", regex.validate("5134-5678-9012-3456"));
-        assertEquals("Space",   "5134567890123456", regex.validate("5134 5678 9012 3456"));
-        assertEquals("MixedA",  "5134567890123456", regex.validate("5134-5678 9012-3456"));
-        assertEquals("MixedB",  "5134567890123456", regex.validate("5134 5678-9012 3456"));
+        assertEquals("5134567890123456", regex.validate("5134567890123456"), "Number");
+        assertEquals("5134567890123456", regex.validate("5134-5678-9012-3456"), "Hyphen");
+        assertEquals("5134567890123456", regex.validate("5134 5678 9012 3456"), "Space");
+        assertEquals("5134567890123456", regex.validate("5134-5678 9012-3456"), "MixedA");
+        assertEquals("5134567890123456", regex.validate("5134 5678-9012 3456"), "MixedB");
 
-        assertFalse("Invalid Separator A",  regex.isValid("5134.5678.9012.3456"));
-        assertFalse("Invalid Separator B",  regex.isValid("5134_5678_9012_3456"));
-        assertFalse("Invalid Grouping A",   regex.isValid("513-45678-9012-3456"));
-        assertFalse("Invalid Grouping B",   regex.isValid("5134-567-89012-3456"));
-        assertFalse("Invalid Grouping C",   regex.isValid("5134-5678-901-23456"));
+        assertFalse(regex.isValid("5134.5678.9012.3456"), "Invalid Separator A");
+        assertFalse(regex.isValid("5134_5678_9012_3456"), "Invalid Separator B");
+        assertFalse(regex.isValid("513-45678-9012-3456"), "Invalid Grouping A");
+        assertFalse(regex.isValid("5134-567-89012-3456"), "Invalid Grouping B");
+        assertFalse(regex.isValid("5134-5678-901-23456"), "Invalid Grouping C");
 
         // *********** Test Validator **********
-        assertEquals("Valid-A", "5500000000000004", validator.validate("5500-0000-0000-0004"));
-        assertEquals("Valid-B", "5424000000000015", validator.validate("5424 0000 0000 0015"));
-        assertEquals("Valid-C", "5301250070000191", validator.validate("5301-250070000191"));
-        assertEquals("Valid-D", "5123456789012346", validator.validate("5123456789012346"));
+        assertEquals("5500000000000004", validator.validate("5500-0000-0000-0004"), "Valid-A");
+        assertEquals("5424000000000015", validator.validate("5424 0000 0000 0015"), "Valid-B");
+        assertEquals("5301250070000191", validator.validate("5301-250070000191"), "Valid-C");
+        assertEquals("5123456789012346", validator.validate("5123456789012346"), "Valid-D");
     }
 
-    public void testGeneric() {
-        final CreditCardValidator ccv = CreditCardValidator.genericCreditCardValidator();
-        for(final String s : VALID_CARDS) {
-            assertTrue(s, ccv.isValid(s));
+    /**
+     * Test the Mastercard Card validator
+     */
+    @Test
+    public void testMastercardValidator() {
+
+        final CodeValidator validator = CreditCardValidator.MASTERCARD_VALIDATOR;
+        final RegexValidator regex = validator.getRegexValidator();
+
+        // ****** Test Regular Expression ******
+        // length 16 and start with a "51-55"
+        assertFalse(regex.isValid("513456789012"), "Length 12");
+        assertFalse(regex.isValid("5134567890123"), "Length 13");
+        assertFalse(regex.isValid("51345678901234"), "Length 14");
+        assertFalse(regex.isValid("513456789012345"), "Length 15");
+        assertTrue(regex.isValid("5134567890123456"), "Length 16");
+        assertFalse(regex.isValid("51345678901234567"), "Length 17");
+        assertFalse(regex.isValid("513456789012345678"), "Length 18");
+        assertFalse(regex.isValid("4134567890123456"), "Prefix 41");
+        assertFalse(regex.isValid("5034567890123456"), "Prefix 50");
+        assertTrue(regex.isValid("5134567890123456"), "Prefix 51");
+        assertTrue(regex.isValid("5234567890123456"), "Prefix 52");
+        assertTrue(regex.isValid("5334567890123456"), "Prefix 53");
+        assertTrue(regex.isValid("5434567890123456"), "Prefix 54");
+        assertTrue(regex.isValid("5534567890123456"), "Prefix 55");
+        assertFalse(regex.isValid("5634567890123456"), "Prefix 56");
+        assertFalse(regex.isValid("6134567890123456"), "Prefix 61");
+        assertFalse(regex.isValid("5134567x90123456"), "Invalid Char");
+
+        // *********** Test Validator **********
+        assertTrue(regex.isValid(ERROR_MASTERCARD), "Valid regex");
+        assertFalse(validator.isValid(ERROR_MASTERCARD), "Invalid");
+        assertNull(validator.validate(ERROR_MASTERCARD), "validate()");
+        assertEquals(VALID_MASTERCARD, validator.validate(VALID_MASTERCARD));
+
+        assertFalse(validator.isValid(VALID_AMEX), "Amex");
+        assertFalse(validator.isValid(VALID_DINERS), "Diners");
+        assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
+        assertTrue(validator.isValid(VALID_MASTERCARD), "Mastercard");
+        assertFalse(validator.isValid(VALID_VISA), "Visa");
+        assertFalse(validator.isValid(VALID_SHORT_VISA), "Visa Short");
+
+        assertTrue(validator.isValid("5500000000000004"), "Valid-A");
+        assertTrue(validator.isValid("5424000000000015"), "Valid-B");
+        assertTrue(validator.isValid("5301250070000191"), "Valid-C");
+        assertTrue(validator.isValid("5123456789012346"), "Valid-D");
+        assertTrue(validator.isValid("5555555555554444"), "Valid-E");
+
+        final RegexValidator rev = validator.getRegexValidator();
+        final String PAD = "0000000000";
+        assertFalse(rev.isValid("222099" + PAD), "222099");
+        for (int i = 222100; i <= 272099; i++) {
+            final String j = Integer.toString(i) + PAD;
+            assertTrue(rev.isValid(j), j);
         }
-        for(final String s : ERROR_CARDS) {
-            assertFalse(s, ccv.isValid(s));
+        assertFalse(rev.isValid("272100" + PAD), "272100");
+    }
+
+    @Test
+    public void testRangeGenerator() {
+        final CreditCardValidator ccv = new CreditCardValidator(
+                new CodeValidator[] { CreditCardValidator.AMEX_VALIDATOR, CreditCardValidator.VISA_VALIDATOR, CreditCardValidator.MASTERCARD_VALIDATOR,
+                        CreditCardValidator.DISCOVER_VALIDATOR, },
+                // Add missing validator
+                new CreditCardRange[] { new CreditCardRange("300", "305", 14, 14), // Diners
+                        new CreditCardRange("3095", null, 14, 14), // Diners
+                        new CreditCardRange("36", null, 14, 14), // Diners
+                        new CreditCardRange("38", "39", 14, 14), // Diners
+                }
+        // we don't have any VPAY examples yet that aren't handled by VISA
+        );
+        for (final String s : VALID_CARDS) {
+            assertTrue(ccv.isValid(s), s);
+        }
+        for (final String s : ERROR_CARDS) {
+            assertFalse(ccv.isValid(s), s);
         }
     }
 
+    @Test
     public void testRangeGeneratorNoLuhn() {
-        final CodeValidator cv = CreditCardValidator.createRangeValidator(
-            new CreditCardRange[]{
-                new CreditCardRange("1",null,6,7),
-                new CreditCardRange("644","65", 8, 8)
-            },
-            null);
+        final CodeValidator cv = CreditCardValidator
+                .createRangeValidator(new CreditCardRange[] { new CreditCardRange("1", null, 6, 7), new CreditCardRange("644", "65", 8, 8) }, null);
         assertTrue(cv.isValid("1990000"));
         assertTrue(cv.isValid("199000"));
         assertFalse(cv.isValid("000000"));
@@ -581,31 +529,7 @@
         assertFalse(cv.isValid("66000000"));
     }
 
-    public void testRangeGenerator() {
-        final CreditCardValidator ccv = new CreditCardValidator(
-            new CodeValidator[] {
-                CreditCardValidator.AMEX_VALIDATOR,
-                CreditCardValidator.VISA_VALIDATOR,
-                CreditCardValidator.MASTERCARD_VALIDATOR,
-                CreditCardValidator.DISCOVER_VALIDATOR,
-            },
-            // Add missing validator
-            new CreditCardRange[]{
-                new CreditCardRange("300", "305", 14, 14), // Diners
-                new CreditCardRange("3095", null, 14, 14), // Diners
-                new CreditCardRange("36",   null, 14, 14), // Diners
-                new CreditCardRange("38",   "39", 14, 14), // Diners
-            }
-            // we don't have any VPAY examples yet that aren't handled by VISA
-            );
-        for(final String s : VALID_CARDS) {
-            assertTrue(s, ccv.isValid(s));
-        }
-        for(final String s : ERROR_CARDS) {
-            assertFalse(s, ccv.isValid(s));
-        }
-    }
-
+    @Test
     public void testValidLength() {
         assertTrue(CreditCardValidator.validLength(14, new CreditCardRange("", "", 14, 14)));
         assertFalse(CreditCardValidator.validLength(15, new CreditCardRange("", "", 14, 14)));
@@ -617,33 +541,93 @@
         assertTrue(CreditCardValidator.validLength(17, new CreditCardRange("", "", 15, 17)));
         assertFalse(CreditCardValidator.validLength(18, new CreditCardRange("", "", 15, 17)));
 
-        assertFalse(CreditCardValidator.validLength(14, new CreditCardRange("", "", new int[]{15, 17})));
-        assertTrue(CreditCardValidator.validLength(15, new CreditCardRange("", "", new int[]{15, 17})));
-        assertFalse(CreditCardValidator.validLength(16, new CreditCardRange("", "", new int[]{15, 17})));
-        assertTrue(CreditCardValidator.validLength(17, new CreditCardRange("", "", new int[]{15, 17})));
-        assertFalse(CreditCardValidator.validLength(18, new CreditCardRange("", "", new int[]{15, 17})));
+        assertFalse(CreditCardValidator.validLength(14, new CreditCardRange("", "", new int[] { 15, 17 })));
+        assertTrue(CreditCardValidator.validLength(15, new CreditCardRange("", "", new int[] { 15, 17 })));
+        assertFalse(CreditCardValidator.validLength(16, new CreditCardRange("", "", new int[] { 15, 17 })));
+        assertTrue(CreditCardValidator.validLength(17, new CreditCardRange("", "", new int[] { 15, 17 })));
+        assertFalse(CreditCardValidator.validLength(18, new CreditCardRange("", "", new int[] { 15, 17 })));
     }
 
-    public void testDisjointRange() {
-        CreditCardValidator ccv = new CreditCardValidator(
-            new CreditCardRange[]{
-                    new CreditCardRange("305", "4", new int[]{13, 16}),
-                }
-            );
-        assertEquals(13, VALID_SHORT_VISA.length());
-        assertEquals(16, VALID_VISA.length());
-        assertEquals(14, VALID_DINERS.length());
-        assertTrue(ccv.isValid(VALID_SHORT_VISA));
-        assertTrue(ccv.isValid(VALID_VISA));
-        assertFalse(ccv.isValid(ERROR_SHORT_VISA));
-        assertFalse(ccv.isValid(ERROR_VISA));
-        assertFalse(ccv.isValid(VALID_DINERS));
-        ccv = new CreditCardValidator(
-            new CreditCardRange[]{
-                    // add 14 as a valid length
-                    new CreditCardRange("305", "4", new int[]{13, 14, 16}),
-                }
-            );
-        assertTrue(ccv.isValid(VALID_DINERS));
+    /**
+     * Test the Visa Card option
+     */
+    @Test
+    public void testVisaOption() {
+        final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.VISA);
+        assertFalse(validator.isValid(ERROR_VISA), "Invalid");
+        assertFalse(validator.isValid(ERROR_SHORT_VISA), "Invalid-S");
+        assertNull(validator.validate(ERROR_VISA), "validate()");
+        assertEquals(VALID_VISA, validator.validate(VALID_VISA));
+        assertEquals(VALID_SHORT_VISA, validator.validate(VALID_SHORT_VISA));
+
+        assertFalse(validator.isValid(VALID_AMEX), "Amex");
+        assertFalse(validator.isValid(VALID_DINERS), "Diners");
+        assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
+        assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
+        assertTrue(validator.isValid(VALID_VISA), "Visa");
+        assertTrue(validator.isValid(VALID_SHORT_VISA), "Visa Short");
+    }
+
+    /**
+     * Test the Visa Card validator
+     */
+    @Test
+    public void testVisaValidator() {
+
+        final CodeValidator validator = CreditCardValidator.VISA_VALIDATOR;
+        final RegexValidator regex = validator.getRegexValidator();
+
+        // ****** Test Regular Expression ******
+        // length 13 or 16, must start with a "4"
+        assertFalse(regex.isValid("423456789012"), "Length 12");
+        assertTrue(regex.isValid("4234567890123"), "Length 13");
+        assertFalse(regex.isValid("42345678901234"), "Length 14");
+        assertFalse(regex.isValid("423456789012345"), "Length 15");
+        assertTrue(regex.isValid("4234567890123456"), "Length 16");
+        assertFalse(regex.isValid("42345678901234567"), "Length 17");
+        assertFalse(regex.isValid("423456789012345678"), "Length 18");
+        assertFalse(regex.isValid("3234567890123"), "Invalid Pref-A");
+        assertFalse(regex.isValid("3234567890123456"), "Invalid Pref-B");
+        assertFalse(regex.isValid("4234567x90123"), "Invalid Char-A");
+        assertFalse(regex.isValid("4234567x90123456"), "Invalid Char-B");
+
+        // *********** Test Validator **********
+        assertTrue(regex.isValid(ERROR_VISA), "Valid regex");
+        assertTrue(regex.isValid(ERROR_SHORT_VISA), "Valid regex-S");
+        assertFalse(validator.isValid(ERROR_VISA), "Invalid");
+        assertFalse(validator.isValid(ERROR_SHORT_VISA), "Invalid-S");
+        assertNull(validator.validate(ERROR_VISA), "validate()");
+        assertEquals(VALID_VISA, validator.validate(VALID_VISA));
+        assertEquals(VALID_SHORT_VISA, validator.validate(VALID_SHORT_VISA));
+
+        assertFalse(validator.isValid(VALID_AMEX), "Amex");
+        assertFalse(validator.isValid(VALID_DINERS), "Diners");
+        assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
+        assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
+        assertTrue(validator.isValid(VALID_VISA), "Visa");
+        assertTrue(validator.isValid(VALID_SHORT_VISA), "Visa Short");
+
+        assertTrue(validator.isValid("4111111111111111"), "Valid-A");
+        assertTrue(validator.isValid("4543059999999982"), "Valid-C");
+        assertTrue(validator.isValid("4462000000000003"), "Valid-B");
+        assertTrue(validator.isValid("4508750000000009"), "Valid-D"); // Electron
+        assertTrue(validator.isValid("4012888888881881"), "Valid-E");
+    }
+
+    @Test
+    public void testVPayOption() {
+        final CreditCardValidator validator = new CreditCardValidator(CreditCardValidator.VPAY);
+        assertTrue(validator.isValid(VALID_VPAY), "Valid");
+        assertTrue(validator.isValid(VALID_VPAY2), "Valid");
+        assertFalse(validator.isValid(ERROR_VPAY), "Invalid");
+        assertEquals(VALID_VPAY, validator.validate(VALID_VPAY));
+        assertEquals(VALID_VPAY2, validator.validate(VALID_VPAY2));
+
+        assertFalse(validator.isValid(VALID_AMEX), "Amex");
+        assertFalse(validator.isValid(VALID_DINERS), "Diners");
+        assertFalse(validator.isValid(VALID_DISCOVER), "Discover");
+        assertFalse(validator.isValid(VALID_MASTERCARD), "Mastercard");
+        assertTrue(validator.isValid(VALID_VISA), "Visa");
+        assertTrue(validator.isValid(VALID_SHORT_VISA), "Visa Short");
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/CurrencyValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/CurrencyValidatorTest.java
index 8fc1ab2..527fa36 100644
--- a/src/test/java/org/apache/commons/validator/routines/CurrencyValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/CurrencyValidatorTest.java
@@ -16,112 +16,62 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
 import java.math.BigDecimal;
 import java.text.DecimalFormatSymbols;
 import java.util.Locale;
 
-import junit.framework.TestCase;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * Test Case for CurrencyValidator.
  */
-public class CurrencyValidatorTest extends TestCase {
+public class CurrencyValidatorTest {
 
     private static final char CURRENCY_SYMBOL = '\u00A4';
 
     private String US_DOLLAR;
     private String UK_POUND;
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public CurrencyValidatorTest(final String name) {
-        super(name);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        US_DOLLAR = (new DecimalFormatSymbols(Locale.US)).getCurrencySymbol();
-        UK_POUND  = (new DecimalFormatSymbols(Locale.UK)).getCurrencySymbol();
-    }
-
-    /**
-     * Tear down
-     * @throws Exception
-     */
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
+    @BeforeEach
+    protected void setUp() {
+        US_DOLLAR = new DecimalFormatSymbols(Locale.US).getCurrencySymbol();
+        UK_POUND = new DecimalFormatSymbols(Locale.UK).getCurrencySymbol();
     }
 
     /**
      * Test Format Type
      */
+    @Test
     public void testFormatType() {
-        assertEquals("Format Type A", 1, CurrencyValidator.getInstance().getFormatType());
-        assertEquals("Format Type B", AbstractNumberValidator.CURRENCY_FORMAT, CurrencyValidator.getInstance().getFormatType());
+        assertEquals(1, CurrencyValidator.getInstance().getFormatType(), "Format Type A");
+        assertEquals(AbstractNumberValidator.CURRENCY_FORMAT, CurrencyValidator.getInstance().getFormatType(), "Format Type B");
     }
 
     /**
-     * Test Valid currency values
+     * Test Invalid integer (non decimal) currency values
      */
-    public void testValid() {
-        // Set the default Locale
-        final Locale origDefault = Locale.getDefault();
-        Locale.setDefault(Locale.UK);
+    @Test
+    public void testIntegerInvalid() {
+        final CurrencyValidator validator = new CurrencyValidator(true, false);
 
-        final BigDecimalValidator validator = CurrencyValidator.getInstance();
-        final BigDecimal expected   = new BigDecimal("1234.56");
-        final BigDecimal negative   = new BigDecimal("-1234.56");
-        final BigDecimal noDecimal  = new BigDecimal("1234.00");
-        final BigDecimal oneDecimal = new BigDecimal("1234.50");
+        // Invalid UK - has decimals
+        assertFalse(validator.isValid(UK_POUND + "1,234.56", Locale.UK), "UK positive");
+        assertFalse(validator.isValid("-" + UK_POUND + "1,234.56", Locale.UK), "UK negative");
 
-        assertEquals("Default locale", expected, validator.validate(UK_POUND + "1,234.56"));
-
-        assertEquals("UK locale",     expected,   validator.validate(UK_POUND  + "1,234.56",   Locale.UK));
-        assertEquals("UK negative",   negative,   validator.validate("-" + UK_POUND  + "1,234.56",  Locale.UK));
-        assertEquals("UK no decimal", noDecimal,  validator.validate(UK_POUND  + "1,234",      Locale.UK));
-        assertEquals("UK 1 decimal",  oneDecimal, validator.validate(UK_POUND  + "1,234.5",    Locale.UK));
-        assertEquals("UK 3 decimal",  expected,   validator.validate(UK_POUND  + "1,234.567",  Locale.UK));
-        assertEquals("UK no symbol",  expected,   validator.validate("1,234.56",    Locale.UK));
-
-        assertEquals("US locale",     expected,   validator.validate(US_DOLLAR + "1,234.56",   Locale.US));
-        assertEquals("US negative",   negative,   validator.validate("(" + US_DOLLAR + "1,234.56)", Locale.US));
-        assertEquals("US no decimal", noDecimal,  validator.validate(US_DOLLAR + "1,234",      Locale.US));
-        assertEquals("US 1 decimal",  oneDecimal, validator.validate(US_DOLLAR + "1,234.5",    Locale.US));
-        assertEquals("US 3 decimal",  expected,   validator.validate(US_DOLLAR + "1,234.567",  Locale.US));
-        assertEquals("US no symbol",  expected,   validator.validate("1,234.56",    Locale.US));
-
-        // Restore the original default
-        Locale.setDefault(origDefault);
-    }
-
-    /**
-     * Test Invalid currency values
-     */
-    public void testInvalid() {
-        final BigDecimalValidator validator = CurrencyValidator.getInstance();
-
-        // Invalid Missing
-        assertFalse("isValid() Null Value",    validator.isValid(null));
-        assertFalse("isValid() Empty Value",   validator.isValid(""));
-        assertNull("validate() Null Value",    validator.validate(null));
-        assertNull("validate() Empty Value",   validator.validate(""));
-
-        // Invalid UK
-        assertFalse("UK wrong symbol",    validator.isValid(US_DOLLAR + "1,234.56",   Locale.UK));
-        assertFalse("UK wrong negative",  validator.isValid("(" + UK_POUND  + "1,234.56)", Locale.UK));
-
-        // Invalid US
-        assertFalse("US wrong symbol",    validator.isValid(UK_POUND + "1,234.56",   Locale.US));
-        assertFalse("US wrong negative",  validator.isValid("-" + US_DOLLAR + "1,234.56",  Locale.US));
+        // Invalid US - has decimals
+        assertFalse(validator.isValid(US_DOLLAR + "1,234.56", Locale.US), "US positive");
+        assertFalse(validator.isValid("(" + US_DOLLAR + "1,234.56)", Locale.US), "US negative");
     }
 
     /**
      * Test Valid integer (non-decimal) currency values
      */
+    @Test
     public void testIntegerValid() {
         // Set the default Locale
         final Locale origDefault = Locale.getDefault();
@@ -131,37 +81,44 @@
         final BigDecimal expected = new BigDecimal("1234.00");
         final BigDecimal negative = new BigDecimal("-1234.00");
 
-        assertEquals("Default locale", expected, validator.validate(UK_POUND +"1,234"));
+        assertEquals(expected, validator.validate(UK_POUND + "1,234"), "Default locale");
 
-        assertEquals("UK locale",      expected, validator.validate(UK_POUND + "1,234",   Locale.UK));
-        assertEquals("UK negative",    negative, validator.validate("-" + UK_POUND + "1,234",  Locale.UK));
+        assertEquals(expected, validator.validate(UK_POUND + "1,234", Locale.UK), "UK locale");
+        assertEquals(negative, validator.validate("-" + UK_POUND + "1,234", Locale.UK), "UK negative");
 
-        assertEquals("US locale",      expected, validator.validate(US_DOLLAR + "1,234",   Locale.US));
-        assertEquals("US negative",    negative, validator.validate("(" + US_DOLLAR + "1,234)", Locale.US));
+        assertEquals(expected, validator.validate(US_DOLLAR + "1,234", Locale.US), "US locale");
+        assertEquals(negative, validator.validate("(" + US_DOLLAR + "1,234)", Locale.US), "US negative");
 
         // Restore the original default
         Locale.setDefault(origDefault);
     }
 
     /**
-     * Test Invalid integer (non decimal) currency values
+     * Test Invalid currency values
      */
-    public void testIntegerInvalid() {
-        final CurrencyValidator validator = new CurrencyValidator(true, false);
+    @Test
+    public void testInvalid() {
+        final BigDecimalValidator validator = CurrencyValidator.getInstance();
 
-        // Invalid UK - has decimals
-        assertFalse("UK positive",    validator.isValid(UK_POUND + "1,234.56",   Locale.UK));
-        assertFalse("UK negative",    validator.isValid("-" + UK_POUND + "1,234.56", Locale.UK));
+        // Invalid Missing
+        assertFalse(validator.isValid(null), "isValid() Null Value");
+        assertFalse(validator.isValid(""), "isValid() Empty Value");
+        assertNull(validator.validate(null), "validate() Null Value");
+        assertNull(validator.validate(""), "validate() Empty Value");
 
-        // Invalid US - has decimals
-        assertFalse("US positive",    validator.isValid(US_DOLLAR + "1,234.56",   Locale.US));
-        assertFalse("US negative",    validator.isValid("(" + US_DOLLAR + "1,234.56)",  Locale.US));
+        // Invalid UK
+        assertFalse(validator.isValid(US_DOLLAR + "1,234.56", Locale.UK), "UK wrong symbol");
+        assertFalse(validator.isValid("(" + UK_POUND + "1,234.56)", Locale.UK), "UK wrong negative");
+
+        // Invalid US
+        assertFalse(validator.isValid(UK_POUND + "1,234.56", Locale.US), "US wrong symbol");
+        assertFalse(validator.isValid("-" + US_DOLLAR + "1,234.56", Locale.US), "US wrong negative");
     }
 
-
     /**
      * Test currency values with a pattern
      */
+    @Test
     public void testPattern() {
         // Set the default Locale
         final Locale origDefault = Locale.getDefault();
@@ -169,25 +126,60 @@
 
         final BigDecimalValidator validator = CurrencyValidator.getInstance();
         final String basicPattern = CURRENCY_SYMBOL + "#,##0.000";
-        final String pattern = basicPattern + ";[" + basicPattern +"]";
-        final BigDecimal expected   = new BigDecimal("1234.567");
-        final BigDecimal negative   = new BigDecimal("-1234.567");
+        final String pattern = basicPattern + ";[" + basicPattern + "]";
+        final BigDecimal expected = new BigDecimal("1234.567");
+        final BigDecimal negative = new BigDecimal("-1234.567");
 
         // Test Pattern
-        assertEquals("default",        expected,   validator.validate(UK_POUND + "1,234.567", pattern));
-        assertEquals("negative",       negative,   validator.validate("[" + UK_POUND + "1,234.567]", pattern));
-        assertEquals("no symbol +ve",  expected,   validator.validate("1,234.567",    pattern));
-        assertEquals("no symbol -ve",  negative,   validator.validate("[1,234.567]",  pattern));
+        assertEquals(expected, validator.validate(UK_POUND + "1,234.567", pattern), "default");
+        assertEquals(negative, validator.validate("[" + UK_POUND + "1,234.567]", pattern), "negative");
+        assertEquals(expected, validator.validate("1,234.567", pattern), "no symbol +ve");
+        assertEquals(negative, validator.validate("[1,234.567]", pattern), "no symbol -ve");
 
         // Test Pattern & Locale
-        assertEquals("default",        expected,   validator.validate(US_DOLLAR + "1,234.567", pattern, Locale.US));
-        assertEquals("negative",       negative,   validator.validate("[" + US_DOLLAR + "1,234.567]", pattern, Locale.US));
-        assertEquals("no symbol +ve",  expected,   validator.validate("1,234.567",    pattern, Locale.US));
-        assertEquals("no symbol -ve",  negative,   validator.validate("[1,234.567]",  pattern, Locale.US));
+        assertEquals(expected, validator.validate(US_DOLLAR + "1,234.567", pattern, Locale.US), "default");
+        assertEquals(negative, validator.validate("[" + US_DOLLAR + "1,234.567]", pattern, Locale.US), "negative");
+        assertEquals(expected, validator.validate("1,234.567", pattern, Locale.US), "no symbol +ve");
+        assertEquals(negative, validator.validate("[1,234.567]", pattern, Locale.US), "no symbol -ve");
 
         // invalid
-        assertFalse("invalid symbol",  validator.isValid(US_DOLLAR + "1,234.567", pattern));
-        assertFalse("invalid symbol",  validator.isValid(UK_POUND  + "1,234.567", pattern, Locale.US));
+        assertFalse(validator.isValid(US_DOLLAR + "1,234.567", pattern), "invalid symbol");
+        assertFalse(validator.isValid(UK_POUND + "1,234.567", pattern, Locale.US), "invalid symbol");
+
+        // Restore the original default
+        Locale.setDefault(origDefault);
+    }
+
+    /**
+     * Test Valid currency values
+     */
+    @Test
+    public void testValid() {
+        // Set the default Locale
+        final Locale origDefault = Locale.getDefault();
+        Locale.setDefault(Locale.UK);
+
+        final BigDecimalValidator validator = CurrencyValidator.getInstance();
+        final BigDecimal expected = new BigDecimal("1234.56");
+        final BigDecimal negative = new BigDecimal("-1234.56");
+        final BigDecimal noDecimal = new BigDecimal("1234.00");
+        final BigDecimal oneDecimal = new BigDecimal("1234.50");
+
+        assertEquals(expected, validator.validate(UK_POUND + "1,234.56"), "Default locale");
+
+        assertEquals(expected, validator.validate(UK_POUND + "1,234.56", Locale.UK), "UK locale");
+        assertEquals(negative, validator.validate("-" + UK_POUND + "1,234.56", Locale.UK), "UK negative");
+        assertEquals(noDecimal, validator.validate(UK_POUND + "1,234", Locale.UK), "UK no decimal");
+        assertEquals(oneDecimal, validator.validate(UK_POUND + "1,234.5", Locale.UK), "UK 1 decimal");
+        assertEquals(expected, validator.validate(UK_POUND + "1,234.567", Locale.UK), "UK 3 decimal");
+        assertEquals(expected, validator.validate("1,234.56", Locale.UK), "UK no symbol");
+
+        assertEquals(expected, validator.validate(US_DOLLAR + "1,234.56", Locale.US), "US locale");
+        assertEquals(negative, validator.validate("(" + US_DOLLAR + "1,234.56)", Locale.US), "US negative");
+        assertEquals(noDecimal, validator.validate(US_DOLLAR + "1,234", Locale.US), "US no decimal");
+        assertEquals(oneDecimal, validator.validate(US_DOLLAR + "1,234.5", Locale.US), "US 1 decimal");
+        assertEquals(expected, validator.validate(US_DOLLAR + "1,234.567", Locale.US), "US 3 decimal");
+        assertEquals(expected, validator.validate("1,234.56", Locale.US), "US no symbol");
 
         // Restore the original default
         Locale.setDefault(origDefault);
diff --git a/src/test/java/org/apache/commons/validator/routines/DateValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/DateValidatorTest.java
index 7293259..c01cf1b 100644
--- a/src/test/java/org/apache/commons/validator/routines/DateValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/DateValidatorTest.java
@@ -16,11 +16,20 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.text.DateFormat;
 import java.util.Date;
 import java.util.Locale;
 import java.util.TimeZone;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Test Case for DateValidator.
  */
@@ -29,155 +38,148 @@
     private DateValidator dateValidator;
 
     /**
-     * Constructor
-     * @param name test name
+     * Sets up test fixtures.
      */
-    public DateValidatorTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set Up.
-     * @throws Exception
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         dateValidator = new DateValidator();
-        validator         = dateValidator;
-    }
-
-    /**
-     * Check that locale providers are set up correctly
-     * If not, the parse will fail
-     */
-    public void testLocaleProviders() throws Exception {
-        final String localeProviders = System.getProperty("java.locale.providers");
-        if (localeProviders != null) { // may be null before Java 9
-            assertTrue("java.locale.providers must start with COMPAT", localeProviders.startsWith("COMPAT"));
-        }
-        final String txt = "3/20/15 10:59:00 PM";  // This relies on the locale format prior to Java 9 to parse correctly
-        final DateFormat dateformat= DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, Locale.US);
-        dateformat.setTimeZone(TimeZone.getTimeZone("GMT"));
-        final Date date = dateformat.parse(txt);
-        assertNotNull(date);
-    }
-    /**
-     * Test DateValidator validate Methods
-     */
-    public void testDateValidatorMethods() {
-        Locale.setDefault(Locale.US);
-        final Locale locale     = Locale.GERMAN;
-        final String pattern    = "yyyy-MM-dd";
-        final String patternVal = "2005-12-31";
-        final String germanVal     = "31 Dez 2005";
-        final String germanPattern = "dd MMM yyyy";
-        final String localeVal  = "31.12.2005";
-        final String defaultVal = "12/31/05";
-        final String XXXX    = "XXXX";
-        final Date expected = createCalendar(null, 20051231, 0).getTime();
-
-        assertEquals("validate(A) default", expected, DateValidator.getInstance().validate(defaultVal));
-        assertEquals("validate(A) locale ", expected, DateValidator.getInstance().validate(localeVal, locale));
-        assertEquals("validate(A) pattern", expected, DateValidator.getInstance().validate(patternVal, pattern));
-        assertEquals("validate(A) both",    expected, DateValidator.getInstance().validate(germanVal, germanPattern, Locale.GERMAN));
-
-        assertTrue("isValid(A) default", DateValidator.getInstance().isValid(defaultVal));
-        assertTrue("isValid(A) locale ", DateValidator.getInstance().isValid(localeVal, locale));
-        assertTrue("isValid(A) pattern", DateValidator.getInstance().isValid(patternVal, pattern));
-        assertTrue("isValid(A) both",    DateValidator.getInstance().isValid(germanVal, germanPattern, Locale.GERMAN));
-
-        assertNull("validate(B) default", DateValidator.getInstance().validate(XXXX));
-        assertNull("validate(B) locale ", DateValidator.getInstance().validate(XXXX, locale));
-        assertNull("validate(B) pattern", DateValidator.getInstance().validate(XXXX, pattern));
-        assertNull("validate(B) both",    DateValidator.getInstance().validate("31 Dec 2005", germanPattern, Locale.GERMAN));
-
-        assertFalse("isValid(B) default", DateValidator.getInstance().isValid(XXXX));
-        assertFalse("isValid(B) locale ", DateValidator.getInstance().isValid(XXXX, locale));
-        assertFalse("isValid(B) pattern", DateValidator.getInstance().isValid(XXXX, pattern));
-        assertFalse("isValid(B) both",    DateValidator.getInstance().isValid("31 Dec 2005", germanPattern, Locale.GERMAN));
-
-        // Test Time Zone
-        final TimeZone zone = (TimeZone.getDefault().getRawOffset() == EET.getRawOffset() ? EST : EET);
-        final Date expectedZone = createCalendar(zone, 20051231, 0).getTime();
-        assertFalse("default/zone same "+zone, expected.getTime() == expectedZone.getTime());
-
-        assertEquals("validate(C) default", expectedZone, DateValidator.getInstance().validate(defaultVal, zone));
-        assertEquals("validate(C) locale ", expectedZone, DateValidator.getInstance().validate(localeVal, locale, zone));
-        assertEquals("validate(C) pattern", expectedZone, DateValidator.getInstance().validate(patternVal, pattern, zone));
-        assertEquals("validate(C) both",    expectedZone, DateValidator.getInstance().validate(germanVal, germanPattern, Locale.GERMAN, zone));
+        validator = dateValidator;
     }
 
     /**
      * Test compare date methods
      */
+    @Test
     public void testCompare() {
-        final int sameTime  = 124522;
+        final int sameTime = 124522;
         final int testDate = 20050823;
-        final Date diffHour    = createDate(GMT, testDate, 115922);    // same date, different time
+        final Date diffHour = createDate(GMT, testDate, 115922); // same date, different time
 
-        final Date value        = createDate(GMT, testDate, sameTime);   // test value
-        final Date date20050824 = createDate(GMT, 20050824, sameTime);   // +1 day
-        final Date date20050822 = createDate(GMT, 20050822, sameTime);   // -1 day
+        final Date value = createDate(GMT, testDate, sameTime); // test value
+        final Date date20050824 = createDate(GMT, 20050824, sameTime); // +1 day
+        final Date date20050822 = createDate(GMT, 20050822, sameTime); // -1 day
 
-        final Date date20050830 = createDate(GMT, 20050830, sameTime);   // +1 week
-        final Date date20050816 = createDate(GMT, 20050816, sameTime);   // -1 week
+        final Date date20050830 = createDate(GMT, 20050830, sameTime); // +1 week
+        final Date date20050816 = createDate(GMT, 20050816, sameTime); // -1 week
 
-        final Date date20050901 = createDate(GMT, 20050901, sameTime);   // +1 month
-        final Date date20050801 = createDate(GMT, 20050801, sameTime);   // same month
-        final Date date20050731 = createDate(GMT, 20050731, sameTime);   // -1 month
+        final Date date20050901 = createDate(GMT, 20050901, sameTime); // +1 month
+        final Date date20050801 = createDate(GMT, 20050801, sameTime); // same month
+        final Date date20050731 = createDate(GMT, 20050731, sameTime); // -1 month
 
-        final Date date20051101 = createDate(GMT, 20051101, sameTime);   // +1 quarter (Feb Start)
-        final Date date20051001 = createDate(GMT, 20051001, sameTime);   // +1 quarter
-        final Date date20050701 = createDate(GMT, 20050701, sameTime);   // same quarter
-        final Date date20050630 = createDate(GMT, 20050630, sameTime);   // -1 quarter
-        final Date date20050110 = createDate(GMT, 20050110, sameTime);   // Previous Year qtr (Fen start)
+        final Date date20051101 = createDate(GMT, 20051101, sameTime); // +1 quarter (Feb Start)
+        final Date date20051001 = createDate(GMT, 20051001, sameTime); // +1 quarter
+        final Date date20050701 = createDate(GMT, 20050701, sameTime); // same quarter
+        final Date date20050630 = createDate(GMT, 20050630, sameTime); // -1 quarter
+        final Date date20050110 = createDate(GMT, 20050110, sameTime); // Previous Year qtr (Fen start)
 
-        final Date date20060101 = createDate(GMT, 20060101, sameTime);   // +1 year
-        final Date date20050101 = createDate(GMT, 20050101, sameTime);   // same year
-        final Date date20041231 = createDate(GMT, 20041231, sameTime);   // -1 year
+        final Date date20060101 = createDate(GMT, 20060101, sameTime); // +1 year
+        final Date date20050101 = createDate(GMT, 20050101, sameTime); // same year
+        final Date date20041231 = createDate(GMT, 20041231, sameTime); // -1 year
 
-        assertEquals("date LT", -1, dateValidator.compareDates(value, date20050824, GMT)); // +1 day
-        assertEquals("date EQ", 0,  dateValidator.compareDates(value, diffHour, GMT));    // same day, diff hour
-        assertEquals("date GT", 1,  dateValidator.compareDates(value, date20050822, GMT)); // -1 day
+        assertEquals(-1, dateValidator.compareDates(value, date20050824, GMT), "date LT"); // +1 day
+        assertEquals(0, dateValidator.compareDates(value, diffHour, GMT), "date EQ"); // same day, diff hour
+        assertEquals(1, dateValidator.compareDates(value, date20050822, GMT), "date GT"); // -1 day
 
-        assertEquals("week LT", -1, dateValidator.compareWeeks(value, date20050830, GMT)); // +1 week
-        assertEquals("week =1", 0,  dateValidator.compareWeeks(value, date20050824, GMT)); // +1 day
-        assertEquals("week =2", 0,  dateValidator.compareWeeks(value, date20050822, GMT)); // same week
-        assertEquals("week =3", 0,  dateValidator.compareWeeks(value, date20050822, GMT)); // -1 day
-        assertEquals("week GT", 1,  dateValidator.compareWeeks(value, date20050816, GMT)); // -1 week
+        assertEquals(-1, dateValidator.compareWeeks(value, date20050830, GMT), "week LT"); // +1 week
+        assertEquals(0, dateValidator.compareWeeks(value, date20050824, GMT), "week =1"); // +1 day
+        assertEquals(0, dateValidator.compareWeeks(value, date20050822, GMT), "week =2"); // same week
+        assertEquals(0, dateValidator.compareWeeks(value, date20050822, GMT), "week =3"); // -1 day
+        assertEquals(1, dateValidator.compareWeeks(value, date20050816, GMT), "week GT"); // -1 week
 
-        assertEquals("mnth LT", -1, dateValidator.compareMonths(value, date20050901, GMT)); // +1 month
-        assertEquals("mnth =1", 0,  dateValidator.compareMonths(value, date20050830, GMT)); // +1 week
-        assertEquals("mnth =2", 0,  dateValidator.compareMonths(value, date20050801, GMT)); // same month
-        assertEquals("mnth =3", 0,  dateValidator.compareMonths(value, date20050816, GMT)); // -1 week
-        assertEquals("mnth GT", 1,  dateValidator.compareMonths(value, date20050731, GMT)); // -1 month
+        assertEquals(-1, dateValidator.compareMonths(value, date20050901, GMT), "mnth LT"); // +1 month
+        assertEquals(0, dateValidator.compareMonths(value, date20050830, GMT), "mnth =1"); // +1 week
+        assertEquals(0, dateValidator.compareMonths(value, date20050801, GMT), "mnth =2"); // same month
+        assertEquals(0, dateValidator.compareMonths(value, date20050816, GMT), "mnth =3"); // -1 week
+        assertEquals(1, dateValidator.compareMonths(value, date20050731, GMT), "mnth GT"); // -1 month
 
-        assertEquals("qtrA <1", -1, dateValidator.compareQuarters(value, date20051101, GMT)); // +1 quarter (Feb)
-        assertEquals("qtrA <2", -1, dateValidator.compareQuarters(value, date20051001, GMT)); // +1 quarter
-        assertEquals("qtrA =1", 0,  dateValidator.compareQuarters(value, date20050901, GMT)); // +1 month
-        assertEquals("qtrA =2", 0,  dateValidator.compareQuarters(value, date20050701, GMT)); // same quarter
-        assertEquals("qtrA =3", 0,  dateValidator.compareQuarters(value, date20050731, GMT)); // -1 month
-        assertEquals("qtrA GT", 1,  dateValidator.compareQuarters(value, date20050630, GMT)); // -1 quarter
+        assertEquals(-1, dateValidator.compareQuarters(value, date20051101, GMT), "qtrA <1"); // +1 quarter (Feb)
+        assertEquals(-1, dateValidator.compareQuarters(value, date20051001, GMT), "qtrA <2"); // +1 quarter
+        assertEquals(0, dateValidator.compareQuarters(value, date20050901, GMT), "qtrA =1"); // +1 month
+        assertEquals(0, dateValidator.compareQuarters(value, date20050701, GMT), "qtrA =2"); // same quarter
+        assertEquals(0, dateValidator.compareQuarters(value, date20050731, GMT), "qtrA =3"); // -1 month
+        assertEquals(1, dateValidator.compareQuarters(value, date20050630, GMT), "qtrA GT"); // -1 quarter
 
         // Change quarter 1 to start in Feb
-        assertEquals("qtrB LT", -1, dateValidator.compareQuarters(value, date20051101, GMT, 2)); // +1 quarter (Feb)
-        assertEquals("qtrB =1", 0,  dateValidator.compareQuarters(value, date20051001, GMT, 2));  // same quarter
-        assertEquals("qtrB =2", 0,  dateValidator.compareQuarters(value, date20050901, GMT, 2)); // +1 month
-        assertEquals("qtrB =3", 1,  dateValidator.compareQuarters(value, date20050701, GMT, 2)); // same quarter
-        assertEquals("qtrB =4", 1,  dateValidator.compareQuarters(value, date20050731, GMT, 2)); // -1 month
-        assertEquals("qtrB GT", 1,  dateValidator.compareQuarters(value, date20050630, GMT, 2)); // -1 quarter
-        assertEquals("qtrB prev", 1,  dateValidator.compareQuarters(value, date20050110, GMT, 2)); // Jan Prev year qtr
+        assertEquals(-1, dateValidator.compareQuarters(value, date20051101, GMT, 2), "qtrB LT"); // +1 quarter (Feb)
+        assertEquals(0, dateValidator.compareQuarters(value, date20051001, GMT, 2), "qtrB =1"); // same quarter
+        assertEquals(0, dateValidator.compareQuarters(value, date20050901, GMT, 2), "qtrB =2"); // +1 month
+        assertEquals(1, dateValidator.compareQuarters(value, date20050701, GMT, 2), "qtrB =3"); // same quarter
+        assertEquals(1, dateValidator.compareQuarters(value, date20050731, GMT, 2), "qtrB =4"); // -1 month
+        assertEquals(1, dateValidator.compareQuarters(value, date20050630, GMT, 2), "qtrB GT"); // -1 quarter
+        assertEquals(1, dateValidator.compareQuarters(value, date20050110, GMT, 2), "qtrB prev"); // Jan Prev year qtr
 
-        assertEquals("year LT", -1, dateValidator.compareYears(value, date20060101, GMT)); // +1 year
-        assertEquals("year EQ", 0,  dateValidator.compareYears(value, date20050101, GMT)); // same year
-        assertEquals("year GT", 1,  dateValidator.compareYears(value, date20041231, GMT)); // -1 year
+        assertEquals(-1, dateValidator.compareYears(value, date20060101, GMT), "year LT"); // +1 year
+        assertEquals(0, dateValidator.compareYears(value, date20050101, GMT), "year EQ"); // same year
+        assertEquals(1, dateValidator.compareYears(value, date20041231, GMT), "year GT"); // -1 year
 
         // Compare using alternative TimeZone
-        final Date sameDayTwoAm    = createDate(GMT, testDate, 20000);
-        assertEquals("date LT", -1, dateValidator.compareDates(value, date20050824, EST)); // +1 day
-        assertEquals("date EQ", 0,  dateValidator.compareDates(value, diffHour, EST));    // same day, diff hour
-        assertEquals("date EQ", 1,  dateValidator.compareDates(value, sameDayTwoAm, EST));    // same day, diff hour
-        assertEquals("date GT", 1,  dateValidator.compareDates(value, date20050822, EST)); // -1 day
+        final Date sameDayTwoAm = createDate(GMT, testDate, 20000);
+        assertEquals(-1, dateValidator.compareDates(value, date20050824, EST), "date LT"); // +1 day
+        assertEquals(0, dateValidator.compareDates(value, diffHour, EST), "date EQ"); // same day, diff hour
+        assertEquals(1, dateValidator.compareDates(value, sameDayTwoAm, EST), "date EQ"); // same day, diff hour
+        assertEquals(1, dateValidator.compareDates(value, date20050822, EST), "date GT"); // -1 day
+    }
+
+    /**
+     * Test DateValidator validate Methods
+     */
+    @Test
+    public void testDateValidatorMethods() {
+        Locale.setDefault(Locale.US);
+        final Locale locale = Locale.GERMAN;
+        final String pattern = "yyyy-MM-dd";
+        final String patternVal = "2005-12-31";
+        final String germanVal = "31 Dez 2005";
+        final String germanPattern = "dd MMM yyyy";
+        final String localeVal = "31.12.2005";
+        final String defaultVal = "12/31/05";
+        final String XXXX = "XXXX";
+        final Date expected = createCalendar(null, 20051231, 0).getTime();
+
+        assertEquals(expected, DateValidator.getInstance().validate(defaultVal), "validate(A) default");
+        assertEquals(expected, DateValidator.getInstance().validate(localeVal, locale), "validate(A) locale ");
+        assertEquals(expected, DateValidator.getInstance().validate(patternVal, pattern), "validate(A) pattern");
+        assertEquals(expected, DateValidator.getInstance().validate(germanVal, germanPattern, Locale.GERMAN), "validate(A) both");
+
+        assertTrue(DateValidator.getInstance().isValid(defaultVal), "isValid(A) default");
+        assertTrue(DateValidator.getInstance().isValid(localeVal, locale), "isValid(A) locale ");
+        assertTrue(DateValidator.getInstance().isValid(patternVal, pattern), "isValid(A) pattern");
+        assertTrue(DateValidator.getInstance().isValid(germanVal, germanPattern, Locale.GERMAN), "isValid(A) both");
+
+        assertNull(DateValidator.getInstance().validate(XXXX), "validate(B) default");
+        assertNull(DateValidator.getInstance().validate(XXXX, locale), "validate(B) locale ");
+        assertNull(DateValidator.getInstance().validate(XXXX, pattern), "validate(B) pattern");
+        assertNull(DateValidator.getInstance().validate("31 Dec 2005", germanPattern, Locale.GERMAN), "validate(B) both");
+
+        assertFalse(DateValidator.getInstance().isValid(XXXX), "isValid(B) default");
+        assertFalse(DateValidator.getInstance().isValid(XXXX, locale), "isValid(B) locale ");
+        assertFalse(DateValidator.getInstance().isValid(XXXX, pattern), "isValid(B) pattern");
+        assertFalse(DateValidator.getInstance().isValid("31 Dec 2005", germanPattern, Locale.GERMAN), "isValid(B) both");
+
+        // Test Time Zone
+        final TimeZone zone = TimeZone.getDefault().getRawOffset() == EET.getRawOffset() ? EST : EET;
+        final Date expectedZone = createCalendar(zone, 20051231, 0).getTime();
+        assertFalse(expected.getTime() == expectedZone.getTime(), "default/zone same " + zone);
+
+        assertEquals(expectedZone, DateValidator.getInstance().validate(defaultVal, zone), "validate(C) default");
+        assertEquals(expectedZone, DateValidator.getInstance().validate(localeVal, locale, zone), "validate(C) locale ");
+        assertEquals(expectedZone, DateValidator.getInstance().validate(patternVal, pattern, zone), "validate(C) pattern");
+        assertEquals(expectedZone, DateValidator.getInstance().validate(germanVal, germanPattern, Locale.GERMAN, zone), "validate(C) both");
+    }
+
+    /**
+     * Check that locale providers are set up correctly If not, the parse will fail
+     */
+    @Test
+    public void testLocaleProviders() throws Exception {
+        final String localeProviders = System.getProperty("java.locale.providers");
+        if (localeProviders != null) { // may be null before Java 9
+            assertTrue(localeProviders.startsWith("COMPAT"), "java.locale.providers must start with COMPAT");
+        }
+        final String txt = "3/20/15 10:59:00 PM"; // This relies on the locale format prior to Java 9 to parse correctly
+        final DateFormat dateformat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, Locale.US);
+        dateformat.setTimeZone(TimeZone.getTimeZone("GMT"));
+        final Date date = dateformat.parse(txt);
+        assertNotNull(date);
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/DomainValidatorStartupTest.java b/src/test/java/org/apache/commons/validator/routines/DomainValidatorStartupTest.java
index b49e7cc..63b88c2 100644
--- a/src/test/java/org/apache/commons/validator/routines/DomainValidatorStartupTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/DomainValidatorStartupTest.java
@@ -35,11 +35,56 @@
 
 /**
  * Startup Tests for the DomainValidator.
+ *
+ * TODO Port to JUnit 5.
  */
 @RunWith(ClassLoaderPerTestRunner.class)
 public class DomainValidatorStartupTest {
 
     @Test
+    public void testCannotUpdate() {
+        DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, "ch"); // OK
+        final DomainValidator dv = DomainValidator.getInstance();
+        assertNotNull(dv);
+        try {
+            DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, "ch");
+            fail("Expected IllegalStateException");
+        } catch (final IllegalStateException ise) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testInstanceOverride() { // Show that the instance picks up static values
+        DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, "gp");
+        DomainValidator.updateTLDOverride(ArrayType.GENERIC_MINUS, "com");
+        DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_PLUS, "cp");
+        DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_MINUS, "ch");
+        DomainValidator validator = DomainValidator.getInstance(false);
+        assertTrue(validator.isValidGenericTld("gp"));
+        assertFalse(validator.isValidGenericTld("com"));
+        assertTrue(validator.isValidCountryCodeTld("cp"));
+        assertFalse(validator.isValidCountryCodeTld("ch"));
+
+        // show we can override them for a new instance
+        final List<DomainValidator.Item> items = new ArrayList<>();
+        items.add(new DomainValidator.Item(ArrayType.GENERIC_MINUS, ""));
+        items.add(new DomainValidator.Item(ArrayType.COUNTRY_CODE_MINUS, ""));
+        validator = DomainValidator.getInstance(false, items);
+        assertTrue(validator.isValidGenericTld("gp"));
+        assertTrue(validator.isValidGenericTld("com")); // Should be true again
+        assertTrue(validator.isValidCountryCodeTld("cp"));
+        assertTrue(validator.isValidCountryCodeTld("ch")); // Should be true again
+
+        // Show the class overrides are unaffected
+        validator = DomainValidator.getInstance(false);
+        assertTrue(validator.isValidGenericTld("gp"));
+        assertFalse(validator.isValidGenericTld("com"));
+        assertTrue(validator.isValidCountryCodeTld("cp"));
+        assertFalse(validator.isValidCountryCodeTld("ch"));
+    }
+
+    @Test
     public void testUpdateBaseArrayCC() {
         final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
                 () -> DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_RO, "com"));
@@ -187,47 +232,4 @@
         assertTrue(validator.isValid("abc.local"));
         assertTrue(validator.isValid("abc.pvt"));
     }
-
-    @Test
-    public void testCannotUpdate() {
-        DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, "ch"); // OK
-        final DomainValidator dv = DomainValidator.getInstance();
-        assertNotNull(dv);
-        try {
-            DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, "ch");
-            fail("Expected IllegalStateException");
-        } catch (final IllegalStateException ise) {
-            // expected
-        }
-    }
-
-    @Test
-    public void testInstanceOverride() { // Show that the instance picks up static values
-        DomainValidator.updateTLDOverride(ArrayType.GENERIC_PLUS, "gp");
-        DomainValidator.updateTLDOverride(ArrayType.GENERIC_MINUS, "com");
-        DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_PLUS, "cp");
-        DomainValidator.updateTLDOverride(ArrayType.COUNTRY_CODE_MINUS, "ch");
-        DomainValidator validator = DomainValidator.getInstance(false);
-        assertTrue(validator.isValidGenericTld("gp"));
-        assertFalse(validator.isValidGenericTld("com"));
-        assertTrue(validator.isValidCountryCodeTld("cp"));
-        assertFalse(validator.isValidCountryCodeTld("ch"));
-
-        // show we can override them for a new instance
-        final List<DomainValidator.Item> items = new ArrayList<>();
-        items.add(new DomainValidator.Item(ArrayType.GENERIC_MINUS, "" ));
-        items.add(new DomainValidator.Item(ArrayType.COUNTRY_CODE_MINUS, ""));
-        validator = DomainValidator.getInstance(false, items);
-        assertTrue(validator.isValidGenericTld("gp"));
-        assertTrue(validator.isValidGenericTld("com")); // Should be true again
-        assertTrue(validator.isValidCountryCodeTld("cp"));
-        assertTrue(validator.isValidCountryCodeTld("ch")); // Should be true again
-
-        // Show the class overrides are unaffected
-        validator = DomainValidator.getInstance(false);
-        assertTrue(validator.isValidGenericTld("gp"));
-        assertFalse(validator.isValidGenericTld("com"));
-        assertTrue(validator.isValidCountryCodeTld("cp"));
-        assertFalse(validator.isValidCountryCodeTld("ch"));
-    }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/DomainValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/DomainValidatorTest.java
index 2a646f3..83f86b4 100644
--- a/src/test/java/org/apache/commons/validator/routines/DomainValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/DomainValidatorTest.java
@@ -16,10 +16,14 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.io.BufferedReader;
 import java.io.Closeable;
 import java.io.File;
-import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
@@ -28,6 +32,8 @@
 import java.net.HttpURLConnection;
 import java.net.IDN;
 import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.HashMap;
@@ -41,386 +47,57 @@
 import java.util.regex.Pattern;
 
 import org.apache.commons.validator.routines.DomainValidator.ArrayType;
-
-import junit.framework.TestCase;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * Tests for the DomainValidator.
  */
-public class DomainValidatorTest extends TestCase {
+public class DomainValidatorTest {
 
-    private DomainValidator validator;
-
-    @Override
-    public void setUp() {
-        validator = DomainValidator.getInstance();
-    }
-
-    public void testValidDomains() {
-        assertTrue("apache.org should validate", validator.isValid("apache.org"));
-        assertTrue("www.google.com should validate", validator.isValid("www.google.com"));
-
-        assertTrue("test-domain.com should validate", validator.isValid("test-domain.com"));
-        assertTrue("test---domain.com should validate", validator.isValid("test---domain.com"));
-        assertTrue("test-d-o-m-ain.com should validate", validator.isValid("test-d-o-m-ain.com"));
-        assertTrue("two-letter domain label should validate", validator.isValid("as.uk"));
-
-        assertTrue("case-insensitive ApAchE.Org should validate", validator.isValid("ApAchE.Org"));
-
-        assertTrue("single-character domain label should validate", validator.isValid("z.com"));
-
-        assertTrue("i.have.an-example.domain.name should validate", validator.isValid("i.have.an-example.domain.name"));
-    }
-
-    public void testInvalidDomains() {
-        assertFalse("bare TLD .org shouldn't validate", validator.isValid(".org"));
-        assertFalse("domain name with spaces shouldn't validate", validator.isValid(" apache.org "));
-        assertFalse("domain name containing spaces shouldn't validate", validator.isValid("apa che.org"));
-        assertFalse("domain name starting with dash shouldn't validate", validator.isValid("-testdomain.name"));
-        assertFalse("domain name ending with dash shouldn't validate", validator.isValid("testdomain-.name"));
-        assertFalse("domain name starting with multiple dashes shouldn't validate", validator.isValid("---c.com"));
-        assertFalse("domain name ending with multiple dashes shouldn't validate", validator.isValid("c--.com"));
-        assertFalse("domain name with invalid TLD shouldn't validate", validator.isValid("apache.rog"));
-
-        assertFalse("URL shouldn't validate", validator.isValid("http://www.apache.org"));
-        assertFalse("Empty string shouldn't validate as domain name", validator.isValid(" "));
-        assertFalse("Null shouldn't validate as domain name", validator.isValid(null));
-    }
-
-    public void testTopLevelDomains() {
-        // infrastructure TLDs
-        assertTrue(".arpa should validate as iTLD", validator.isValidInfrastructureTld(".arpa"));
-        assertFalse(".com shouldn't validate as iTLD", validator.isValidInfrastructureTld(".com"));
-
-        // generic TLDs
-        assertTrue(".name should validate as gTLD", validator.isValidGenericTld(".name"));
-        assertFalse(".us shouldn't validate as gTLD", validator.isValidGenericTld(".us"));
-
-        // country code TLDs
-        assertTrue(".uk should validate as ccTLD", validator.isValidCountryCodeTld(".uk"));
-        assertFalse(".org shouldn't validate as ccTLD", validator.isValidCountryCodeTld(".org"));
-
-        // case-insensitive
-        assertTrue(".COM should validate as TLD", validator.isValidTld(".COM"));
-        assertTrue(".BiZ should validate as TLD", validator.isValidTld(".BiZ"));
-
-        // corner cases
-        assertFalse("invalid TLD shouldn't validate", validator.isValid(".nope")); // TODO this is not guaranteed invalid forever
-        assertFalse("empty string shouldn't validate as TLD", validator.isValid(""));
-        assertFalse("null shouldn't validate as TLD", validator.isValid(null));
-    }
-
-    public void testAllowLocal() {
-       final DomainValidator noLocal = DomainValidator.getInstance(false);
-       final DomainValidator allowLocal = DomainValidator.getInstance(true);
-
-       // Default is false, and should use singletons
-       assertEquals(noLocal, validator);
-
-       // Default won't allow local
-       assertFalse("localhost.localdomain should validate", noLocal.isValid("localhost.localdomain"));
-       assertFalse("localhost should validate", noLocal.isValid("localhost"));
-
-       // But it may be requested
-       assertTrue("localhost.localdomain should validate", allowLocal.isValid("localhost.localdomain"));
-       assertTrue("localhost should validate", allowLocal.isValid("localhost"));
-       assertTrue("hostname should validate", allowLocal.isValid("hostname"));
-       assertTrue("machinename should validate", allowLocal.isValid("machinename"));
-
-       // Check the localhost one with a few others
-       assertTrue("apache.org should validate", allowLocal.isValid("apache.org"));
-       assertFalse("domain name with spaces shouldn't validate", allowLocal.isValid(" apache.org "));
-    }
-
-    public void testIDN() {
-       assertTrue("b\u00fccher.ch in IDN should validate", validator.isValid("www.xn--bcher-kva.ch"));
-    }
-
-    public void testIDNJava6OrLater() {
-        final String version = System.getProperty("java.version");
-        if (version.compareTo("1.6") < 0) {
-            System.out.println("Cannot run Unicode IDN tests");
-            return; // Cannot run the test
-        } // xn--d1abbgf6aiiy.xn--p1ai http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„
-       assertTrue("b\u00fccher.ch should validate", validator.isValid("www.b\u00fccher.ch"));
-       assertTrue("xn--d1abbgf6aiiy.xn--p1ai should validate", validator.isValid("xn--d1abbgf6aiiy.xn--p1ai"));
-       assertTrue("ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„ should validate", validator.isValid("ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„"));
-       assertFalse("www.\uFFFD.ch FFFD should fail", validator.isValid("www.\uFFFD.ch"));
-    }
-
-    // RFC2396: domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
-    public void testRFC2396domainlabel() { // use fixed valid TLD
-        assertTrue("a.ch should validate", validator.isValid("a.ch"));
-        assertTrue("9.ch should validate", validator.isValid("9.ch"));
-        assertTrue("az.ch should validate", validator.isValid("az.ch"));
-        assertTrue("09.ch should validate", validator.isValid("09.ch"));
-        assertTrue("9-1.ch should validate", validator.isValid("9-1.ch"));
-        assertFalse("91-.ch should not validate", validator.isValid("91-.ch"));
-        assertFalse("-.ch should not validate", validator.isValid("-.ch"));
-    }
-
-    // RFC2396 toplabel = alpha | alpha *( alphanum | "-" ) alphanum
-    public void testRFC2396toplabel() {
-        // These tests use non-existent TLDs so currently need to use a package protected method
-        assertTrue("a.c (alpha) should validate", validator.isValidDomainSyntax("a.c"));
-        assertTrue("a.cc (alpha alpha) should validate", validator.isValidDomainSyntax("a.cc"));
-        assertTrue("a.c9 (alpha alphanum) should validate", validator.isValidDomainSyntax("a.c9"));
-        assertTrue("a.c-9 (alpha - alphanum) should validate", validator.isValidDomainSyntax("a.c-9"));
-        assertTrue("a.c-z (alpha - alpha) should validate", validator.isValidDomainSyntax("a.c-z"));
-
-        assertFalse("a.9c (alphanum alpha) should fail", validator.isValidDomainSyntax("a.9c"));
-        assertFalse("a.c- (alpha -) should fail", validator.isValidDomainSyntax("a.c-"));
-        assertFalse("a.- (-) should fail", validator.isValidDomainSyntax("a.-"));
-        assertFalse("a.-9 (- alphanum) should fail", validator.isValidDomainSyntax("a.-9"));
-    }
-
-    public void testDomainNoDots() {// rfc1123
-        assertTrue("a (alpha) should validate", validator.isValidDomainSyntax("a"));
-        assertTrue("9 (alphanum) should validate", validator.isValidDomainSyntax("9"));
-        assertTrue("c-z (alpha - alpha) should validate", validator.isValidDomainSyntax("c-z"));
-
-        assertFalse("c- (alpha -) should fail", validator.isValidDomainSyntax("c-"));
-        assertFalse("-c (- alpha) should fail", validator.isValidDomainSyntax("-c"));
-        assertFalse("- (-) should fail", validator.isValidDomainSyntax("-"));
-    }
-
-    public void testValidator297() {
-        assertTrue("xn--d1abbgf6aiiy.xn--p1ai should validate", validator.isValid("xn--d1abbgf6aiiy.xn--p1ai")); // This uses a valid TLD
-     }
-
-    // labels are a max of 63 chars and domains 253
-    public void testValidator306() {
-        final String longString = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789A";
-        assertEquals(63, longString.length()); // 26 * 2 + 11
-
-        assertTrue("63 chars label should validate", validator.isValidDomainSyntax(longString+".com"));
-        assertFalse("64 chars label should fail", validator.isValidDomainSyntax(longString+"x.com"));
-
-        assertTrue("63 chars TLD should validate", validator.isValidDomainSyntax("test."+longString));
-        assertFalse("64 chars TLD should fail", validator.isValidDomainSyntax("test.x"+longString));
-
-        final String longDomain =
-                longString
-                + "." + longString
-                + "." + longString
-                + "." + longString.substring(0,61)
-                ;
-        assertEquals(253, longDomain.length());
-        assertTrue("253 chars domain should validate", validator.isValidDomainSyntax(longDomain));
-        assertFalse("254 chars domain should fail", validator.isValidDomainSyntax(longDomain+"x"));
-    }
-
-    // Check that IDN.toASCII behaves as it should (when wrapped by DomainValidator.unicodeToASCII)
-    // Tests show that method incorrectly trims a trailing "." character
-    public void testUnicodeToASCII() {
-        final String[] asciidots = {
-                "",
-                ",",
-                ".", // fails IDN.toASCII, but should pass wrapped version
-                "a.", // ditto
-                "a.b",
-                "a..b",
-                "a...b",
-                ".a",
-                "..a",
-        };
-        for(final String s : asciidots) {
-            assertEquals(s,DomainValidator.unicodeToASCII(s));
-        }
-        // RFC3490 3.1. 1)
-//      Whenever dots are used as label separators, the following
-//      characters MUST be recognized as dots: U+002E (full stop), U+3002
-//      (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61
-//      (halfwidth ideographic full stop).
-        final String otherDots[][] = {
-                {"b\u3002", "b.",},
-                {"b\uFF0E", "b.",},
-                {"b\uFF61", "b.",},
-                {"\u3002", ".",},
-                {"\uFF0E", ".",},
-                {"\uFF61", ".",},
-        };
-        for(final String s[] : otherDots) {
-            assertEquals(s[1],DomainValidator.unicodeToASCII(s[0]));
-        }
-    }
-
-    // Check if IDN.toASCII is broken or not
-    public void testIsIDNtoASCIIBroken() {
-        System.out.println(">>DomainValidatorTest.testIsIDNtoASCIIBroken()");
-        final String input = ".";
-        final boolean ok = input.equals(IDN.toASCII(input));
-        System.out.println("IDN.toASCII is " + (ok? "OK" : "BROKEN"));
-        final String props[] = {
-        "java.version", //    Java Runtime Environment version
-        "java.vendor", // Java Runtime Environment vendor
-        "java.vm.specification.version", //   Java Virtual Machine specification version
-        "java.vm.specification.vendor", //    Java Virtual Machine specification vendor
-        "java.vm.specification.name", //  Java Virtual Machine specification name
-        "java.vm.version", // Java Virtual Machine implementation version
-        "java.vm.vendor", //  Java Virtual Machine implementation vendor
-        "java.vm.name", //    Java Virtual Machine implementation name
-        "java.specification.version", //  Java Runtime Environment specification version
-        "java.specification.vendor", //   Java Runtime Environment specification vendor
-        "java.specification.name", // Java Runtime Environment specification name
-        "java.class.version", //  Java class format version number
-        };
-        for(final String t : props) {
-            System.out.println(t + "=" + System.getProperty(t));
-        }
-        System.out.println("<<DomainValidatorTest.testIsIDNtoASCIIBroken()");
-        assertTrue(true); // dummy assertion to satisfy lint
-    }
-
-    // Check array is sorted and is lower-case
-    public void test_INFRASTRUCTURE_TLDS_sortedAndLowerCase() throws Exception {
-        final boolean sorted = isSortedLowerCase("INFRASTRUCTURE_TLDS");
-        assertTrue(sorted);
-    }
-
-    // Check array is sorted and is lower-case
-    public void test_COUNTRY_CODE_TLDS_sortedAndLowerCase() throws Exception {
-        final boolean sorted = isSortedLowerCase("COUNTRY_CODE_TLDS");
-        assertTrue(sorted);
-    }
-
-    // Check array is sorted and is lower-case
-    public void test_GENERIC_TLDS_sortedAndLowerCase() throws Exception {
-        final boolean sorted = isSortedLowerCase("GENERIC_TLDS");
-        assertTrue(sorted);
-    }
-
-    // Check array is sorted and is lower-case
-    public void test_LOCAL_TLDS_sortedAndLowerCase() throws Exception {
-        final boolean sorted = isSortedLowerCase("LOCAL_TLDS");
-        assertTrue(sorted);
-    }
-
-    public void testEnumIsPublic() {
-        assertTrue(Modifier.isPublic(DomainValidator.ArrayType.class.getModifiers()));
-    }
-
-    public void testGetArray() {
-        assertNotNull(DomainValidator.getTLDEntries(ArrayType.COUNTRY_CODE_MINUS));
-        assertNotNull(DomainValidator.getTLDEntries(ArrayType.COUNTRY_CODE_PLUS));
-        assertNotNull(DomainValidator.getTLDEntries(ArrayType.GENERIC_MINUS));
-        assertNotNull(DomainValidator.getTLDEntries(ArrayType.GENERIC_PLUS));
-        assertNotNull(DomainValidator.getTLDEntries(ArrayType.LOCAL_MINUS));
-        assertNotNull(DomainValidator.getTLDEntries(ArrayType.LOCAL_PLUS));
-        assertNotNull(DomainValidator.getTLDEntries(ArrayType.COUNTRY_CODE_RO));
-        assertNotNull(DomainValidator.getTLDEntries(ArrayType.GENERIC_RO));
-        assertNotNull(DomainValidator.getTLDEntries(ArrayType.INFRASTRUCTURE_RO));
-        assertNotNull(DomainValidator.getTLDEntries(ArrayType.LOCAL_RO));
-    }
-
-    // Download and process local copy of http://data.iana.org/TLD/tlds-alpha-by-domain.txt
-    // Check if the internal TLD table is up to date
-    // Check if the internal TLD tables have any spurious entries
-    public static void main(final String a[]) throws Exception {
-        // Check the arrays first as this affects later checks
-        // Doing this here makes it easier when updating the lists
-        boolean OK = true;
-        for(final String list : new String[]{"INFRASTRUCTURE_TLDS","COUNTRY_CODE_TLDS","GENERIC_TLDS","LOCAL_TLDS"}) {
-            OK &= isSortedLowerCase(list);
-        }
-        if (!OK) {
-            System.out.println("Fix arrays before retrying; cannot continue");
-            return;
-        }
-        final Set<String> ianaTlds = new HashSet<>(); // keep for comparison with array contents
-        final DomainValidator dv = DomainValidator.getInstance();
-        final File txtFile = new File("target/tlds-alpha-by-domain.txt");
-        final long timestamp = download(txtFile, "https://data.iana.org/TLD/tlds-alpha-by-domain.txt", 0L);
-        final File htmlFile = new File("target/tlds-alpha-by-domain.html");
-        // N.B. sometimes the html file may be updated a day or so after the txt file
-        // if the txt file contains entries not found in the html file, try again in a day or two
-        download(htmlFile,"https://www.iana.org/domains/root/db", timestamp);
-
-        final BufferedReader br = new BufferedReader(new FileReader(txtFile));
-        String line;
-        final String header;
-        line = br.readLine(); // header
-        if (!line.startsWith("# Version ")) {
-            br.close();
-            throw new IOException("File does not have expected Version header");
-        }
-        header = line.substring(2);
-        final boolean generateUnicodeTlds = false; // Change this to generate Unicode TLDs as well
-
-        // Parse html page to get entries
-        final Map<String, String[]> htmlInfo = getHtmlInfo(htmlFile);
-        final Map<String, String> missingTLD = new TreeMap<>(); // stores entry and comments as String[]
-        final Map<String, String> missingCC = new TreeMap<>();
-        while((line = br.readLine()) != null) {
-            if (!line.startsWith("#")) {
-                final String unicodeTld; // only different from asciiTld if that was punycode
-                final String asciiTld = line.toLowerCase(Locale.ENGLISH);
-                if (line.startsWith("XN--")) {
-                    unicodeTld = IDN.toUnicode(line);
-                } else {
-                    unicodeTld = asciiTld;
-                }
-                if (!dv.isValidTld(asciiTld)) {
-                    final String [] info = htmlInfo.get(asciiTld);
-                    if (info != null) {
-                        final String type = info[0];
-                        final String comment = info[1];
-                        if ("country-code".equals(type)) { // Which list to use?
-                            missingCC.put(asciiTld, unicodeTld + " " + comment);
-                            if (generateUnicodeTlds) {
-                                missingCC.put(unicodeTld, asciiTld + " " + comment);
-                            }
-                        } else {
-                            missingTLD.put(asciiTld, unicodeTld + " " + comment);
-                            if (generateUnicodeTlds) {
-                                missingTLD.put(unicodeTld, asciiTld + " " + comment);
-                            }
-                        }
-                    } else {
-                        System.err.println("Expected to find HTML info for "+ asciiTld);
-                    }
-                }
-                ianaTlds.add(asciiTld);
-                // Don't merge these conditions; generateUnicodeTlds is final so needs to be separate to avoid a warning
-                if (generateUnicodeTlds && !unicodeTld.equals(asciiTld)) {
-                    ianaTlds.add(unicodeTld);
-                }
+    private static void closeQuietly(final Closeable in) {
+        if (in != null) {
+            try {
+                in.close();
+            } catch (final IOException e) {
             }
         }
-        br.close();
-        // List html entries not in TLD text list
-        for(final String key : (new TreeMap<>(htmlInfo)).keySet()) {
-            if (!ianaTlds.contains(key)) {
-                if (isNotInRootZone(key)) {
-                    System.out.println("INFO: HTML entry not yet in root zone: "+key);
-                } else {
-                    System.err.println("WARN: Expected to find text entry for html: "+key);
-                }
-            }
-        }
-        if (!missingTLD.isEmpty()) {
-            printMap(header, missingTLD, "GENERIC_TLDS");
-        }
-        if (!missingCC.isEmpty()) {
-            printMap(header, missingCC, "COUNTRY_CODE_TLDS");
-        }
-        // Check if internal tables contain any additional entries
-        isInIanaList("INFRASTRUCTURE_TLDS", ianaTlds);
-        isInIanaList("COUNTRY_CODE_TLDS", ianaTlds);
-        isInIanaList("GENERIC_TLDS", ianaTlds);
-        // Don't check local TLDS isInIanaList("LOCAL_TLDS", ianaTlds);
-        System.out.println("Finished checks");
     }
 
-    private static void printMap(final String header, final Map<String, String> map, final String string) {
-        System.out.println("Entries missing from "+ string +" List\n");
-        if (header != null) {
-            System.out.println("        // Taken from " + header);
+    /*
+     * Download a file if it is more recent than our cached copy. Unfortunately the server does not seem to honor If-Modified-Since for the Html page, so we
+     * check if it is newer than the txt file and skip download if so
+     */
+    private static long download(final File file, final String tldUrl, final long timestamp) throws IOException {
+        final int HOUR = 60 * 60 * 1000; // an hour in ms
+        final long modTime;
+        // For testing purposes, don't download files more than once an hour
+        if (file.canRead()) {
+            modTime = file.lastModified();
+            if (modTime > System.currentTimeMillis() - HOUR) {
+                System.out.println("Skipping download - found recent " + file);
+                return modTime;
+            }
+        } else {
+            modTime = 0;
         }
-        for (Entry<String, String> me : map.entrySet()) {
-            System.out.println("        \"" + me.getKey() + "\", // " + me.getValue());
+        final HttpURLConnection hc = (HttpURLConnection) new URL(tldUrl).openConnection();
+        if (modTime > 0) {
+            final SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");// Sun, 06 Nov 1994 08:49:37 GMT
+            final String since = sdf.format(new Date(modTime));
+            hc.addRequestProperty("If-Modified-Since", since);
+            System.out.println("Found " + file + " with date " + since);
         }
-        System.out.println("\nDone");
+        if (hc.getResponseCode() == 304) {
+            System.out.println("Already have most recent " + tldUrl);
+        } else {
+            System.out.println("Downloading " + tldUrl);
+            try (InputStream is = hc.getInputStream()) {
+                Files.copy(is, file.toPath(), StandardCopyOption.REPLACE_EXISTING);
+            }
+            System.out.println("Done");
+        }
+        return file.lastModified();
     }
 
     private static Map<String, String[]> getHtmlInfo(final File f) throws IOException {
@@ -434,134 +111,52 @@
 //        <td>Ålands landskapsregering</td>
         final Pattern comment = Pattern.compile("\\s+<td>([^<]+)</td>");
 
-        final BufferedReader br = new BufferedReader(new FileReader(f));
-        String line;
-        while((line=br.readLine())!=null){
-            final Matcher m = domain.matcher(line);
-            if (m.lookingAt()) {
-                final String dom = m.group(1);
-                String typ = "??";
-                String com = "??";
-                line = br.readLine();
-                while (line.matches("^\\s*$")) { // extra blank lines introduced
+        try (BufferedReader br = new BufferedReader(new FileReader(f))) {
+            String line;
+            while ((line = br.readLine()) != null) {
+                final Matcher m = domain.matcher(line);
+                if (m.lookingAt()) {
+                    final String dom = m.group(1);
+                    String typ = "??";
+                    String com = "??";
                     line = br.readLine();
-                }
-                final Matcher t = type.matcher(line);
-                if (t.lookingAt()) {
-                    typ = t.group(1);
-                    line = br.readLine();
-                    if (line.matches("\\s+<!--.*")) {
-                        while(!line.matches(".*-->.*")){
-                            line = br.readLine();
-                        }
+                    while (line.matches("^\\s*$")) { // extra blank lines introduced
                         line = br.readLine();
                     }
-                    // Should have comment; is it wrapped?
-                    while(!line.matches(".*</td>.*")){
-                        line += " " +br.readLine();
-                    }
-                    final Matcher n = comment.matcher(line);
-                    if (n.lookingAt()) {
-                        com = n.group(1);
-                    }
-                    // Don't save unused entries
-                    if (com.contains("Not assigned") || com.contains("Retired") || typ.equals("test")) {
+                    final Matcher t = type.matcher(line);
+                    if (t.lookingAt()) {
+                        typ = t.group(1);
+                        line = br.readLine();
+                        if (line.matches("\\s+<!--.*")) {
+                            while (!line.matches(".*-->.*")) {
+                                line = br.readLine();
+                            }
+                            line = br.readLine();
+                        }
+                        // Should have comment; is it wrapped?
+                        while (!line.matches(".*</td>.*")) {
+                            line += " " + br.readLine();
+                        }
+                        final Matcher n = comment.matcher(line);
+                        if (n.lookingAt()) {
+                            com = n.group(1);
+                        }
+                        // Don't save unused entries
+                        if (com.contains("Not assigned") || com.contains("Retired") || typ.equals("test")) {
 //                        System.out.println("Ignored: " + typ + " " + dom + " " +com);
-                    } else {
-                        info.put(dom.toLowerCase(Locale.ENGLISH), new String[]{typ, com});
+                        } else {
+                            info.put(dom.toLowerCase(Locale.ENGLISH), new String[] { typ, com });
 //                        System.out.println("Storing: " + typ + " " + dom + " " +com);
+                        }
+                    } else {
+                        System.err.println("Unexpected type: " + line);
                     }
-                } else {
-                    System.err.println("Unexpected type: " + line);
                 }
             }
         }
-        br.close();
         return info;
     }
 
-    /*
-     * Download a file if it is more recent than our cached copy.
-     * Unfortunately the server does not seem to honor If-Modified-Since for the
-     * Html page, so we check if it is newer than the txt file and skip download if so
-     */
-    private static long download(final File f, final String tldurl, final long timestamp) throws IOException {
-        final int HOUR = 60*60*1000; // an hour in ms
-        final long modTime;
-        // For testing purposes, don't download files more than once an hour
-        if (f.canRead()) {
-            modTime = f.lastModified();
-            if (modTime > System.currentTimeMillis()-HOUR) {
-                System.out.println("Skipping download - found recent " + f);
-                return modTime;
-            }
-        } else {
-            modTime = 0;
-        }
-        final HttpURLConnection hc = (HttpURLConnection) new URL(tldurl).openConnection();
-        if (modTime > 0) {
-            final SimpleDateFormat sdf = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss z");//Sun, 06 Nov 1994 08:49:37 GMT
-            final String since = sdf.format(new Date(modTime));
-            hc.addRequestProperty("If-Modified-Since", since);
-            System.out.println("Found " + f + " with date " + since);
-        }
-        if (hc.getResponseCode() == 304) {
-            System.out.println("Already have most recent " + tldurl);
-        } else {
-            System.out.println("Downloading " + tldurl);
-            final byte buff[] = new byte[1024];
-            final InputStream is = hc.getInputStream();
-
-            final FileOutputStream fos = new FileOutputStream(f);
-            int len;
-            while((len=is.read(buff)) != -1) {
-                fos.write(buff, 0, len);
-            }
-            fos.close();
-            is.close();
-            System.out.println("Done");
-        }
-        return f.lastModified();
-    }
-
-    /**
-     * Check whether the domain is in the root zone currently.
-     * Reads the URL http://www.iana.org/domains/root/db/*domain*.html
-     * (using a local disk cache)
-     * and checks for the string "This domain is not present in the root zone at this time."
-     * @param domain the domain to check
-     * @return true if the string is found
-     */
-    private static boolean isNotInRootZone(final String domain) {
-        final String tldurl = "http://www.iana.org/domains/root/db/" + domain + ".html";
-        final File rootCheck = new File("target","tld_" + domain + ".html");
-        BufferedReader in = null;
-        try {
-            download(rootCheck, tldurl, 0L);
-            in = new BufferedReader(new FileReader(rootCheck));
-            String inputLine;
-            while ((inputLine = in.readLine()) != null) {
-                if (inputLine.contains("This domain is not present in the root zone at this time.")) {
-                    return true;
-                }
-            }
-            in.close();
-        } catch (final IOException e) {
-        } finally {
-            closeQuietly(in);
-        }
-        return false;
-    }
-
-    private static void closeQuietly(final Closeable in) {
-        if (in != null) {
-            try {
-                in.close();
-            } catch (final IOException e) {
-            }
-        }
-    }
-
     // isInIanaList and isSorted are split into two methods.
     // If/when access to the arrays is possible without reflection, the intermediate
     // methods can be dropped
@@ -581,7 +176,7 @@
         }
     }
 
-    private static boolean isInIanaList(final String name, final String [] array, final Set<String> ianaTlds) {
+    private static boolean isInIanaList(final String name, final String[] array, final Set<String> ianaTlds) {
         for (final String element : array) {
             if (!ianaTlds.contains(element)) {
                 System.out.println(name + " contains unexpected value: " + element);
@@ -590,6 +185,38 @@
         return true;
     }
 
+    private static boolean isLowerCase(final String string) {
+        return string.equals(string.toLowerCase(Locale.ENGLISH));
+    }
+
+    /**
+     * Check whether the domain is in the root zone currently. Reads the URL http://www.iana.org/domains/root/db/*domain*.html (using a local disk cache) and
+     * checks for the string "This domain is not present in the root zone at this time."
+     *
+     * @param domain the domain to check
+     * @return true if the string is found
+     */
+    private static boolean isNotInRootZone(final String domain) {
+        final String tldUrl = "http://www.iana.org/domains/root/db/" + domain + ".html";
+        final File rootCheck = new File("target", "tld_" + domain + ".html");
+        BufferedReader in = null;
+        try {
+            download(rootCheck, tldUrl, 0L);
+            in = new BufferedReader(new FileReader(rootCheck));
+            String inputLine;
+            while ((inputLine = in.readLine()) != null) {
+                if (inputLine.contains("This domain is not present in the root zone at this time.")) {
+                    return true;
+                }
+            }
+            in.close();
+        } catch (final IOException e) {
+        } finally {
+            closeQuietly(in);
+        }
+        return false;
+    }
+
     private static boolean isSortedLowerCase(final String arrayName) throws Exception {
         final Field f = DomainValidator.class.getDeclaredField(arrayName);
         final boolean isPrivate = Modifier.isPrivate(f.getModifiers());
@@ -606,19 +233,15 @@
         }
     }
 
-    private static boolean isLowerCase(final String string) {
-        return string.equals(string.toLowerCase(Locale.ENGLISH));
-    }
-
     // Check if an array is strictly sorted - and lowerCase
-    private static boolean isSortedLowerCase(final String name, final String [] array) {
+    private static boolean isSortedLowerCase(final String name, final String[] array) {
         boolean sorted = true;
         boolean strictlySorted = true;
         final int length = array.length;
-        boolean lowerCase = isLowerCase(array[length-1]); // Check the last entry
-        for(int i = 0; i < length-1; i++) { // compare all but last entry with next
+        boolean lowerCase = isLowerCase(array[length - 1]); // Check the last entry
+        for (int i = 0; i < length - 1; i++) { // compare all but last entry with next
             final String entry = array[i];
-            final String nextEntry = array[i+1];
+            final String nextEntry = array[i + 1];
             final int cmp = entry.compareTo(nextEntry);
             if (cmp > 0) { // out of order
                 System.out.println("Out of order entry: " + entry + " < " + nextEntry + " in " + name);
@@ -634,4 +257,377 @@
         }
         return sorted && strictlySorted && lowerCase;
     }
+
+    // Download and process local copy of https://data.iana.org/TLD/tlds-alpha-by-domain.txt
+    // Check if the internal TLD table is up to date
+    // Check if the internal TLD tables have any spurious entries
+    public static void main(final String a[]) throws Exception {
+        // Check the arrays first as this affects later checks
+        // Doing this here makes it easier when updating the lists
+        boolean OK = true;
+        for (final String list : new String[] { "INFRASTRUCTURE_TLDS", "COUNTRY_CODE_TLDS", "GENERIC_TLDS", "LOCAL_TLDS" }) {
+            OK &= isSortedLowerCase(list);
+        }
+        if (!OK) {
+            System.out.println("Fix arrays before retrying; cannot continue");
+            return;
+        }
+        final Set<String> ianaTlds = new HashSet<>(); // keep for comparison with array contents
+        final DomainValidator dv = DomainValidator.getInstance();
+        final File txtFile = new File("target/tlds-alpha-by-domain.txt");
+        final long timestamp = download(txtFile, "https://data.iana.org/TLD/tlds-alpha-by-domain.txt", 0L);
+        final File htmlFile = new File("target/tlds-alpha-by-domain.html");
+        // N.B. sometimes the html file may be updated a day or so after the txt file
+        // if the txt file contains entries not found in the html file, try again in a day or two
+        download(htmlFile, "https://www.iana.org/domains/root/db", timestamp);
+
+        final BufferedReader br = new BufferedReader(new FileReader(txtFile));
+        String line;
+        final String header;
+        line = br.readLine(); // header
+        if (!line.startsWith("# Version ")) {
+            br.close();
+            throw new IOException("File does not have expected Version header");
+        }
+        header = line.substring(2);
+        final boolean generateUnicodeTlds = false; // Change this to generate Unicode TLDs as well
+
+        // Parse html page to get entries
+        final Map<String, String[]> htmlInfo = getHtmlInfo(htmlFile);
+        final Map<String, String> missingTLD = new TreeMap<>(); // stores entry and comments as String[]
+        final Map<String, String> missingCC = new TreeMap<>();
+        while ((line = br.readLine()) != null) {
+            if (!line.startsWith("#")) {
+                final String unicodeTld; // only different from asciiTld if that was punycode
+                final String asciiTld = line.toLowerCase(Locale.ENGLISH);
+                if (line.startsWith("XN--")) {
+                    unicodeTld = IDN.toUnicode(line);
+                } else {
+                    unicodeTld = asciiTld;
+                }
+                if (!dv.isValidTld(asciiTld)) {
+                    final String[] info = htmlInfo.get(asciiTld);
+                    if (info != null) {
+                        final String type = info[0];
+                        final String comment = info[1];
+                        if ("country-code".equals(type)) { // Which list to use?
+                            missingCC.put(asciiTld, unicodeTld + " " + comment);
+                            if (generateUnicodeTlds) {
+                                missingCC.put(unicodeTld, asciiTld + " " + comment);
+                            }
+                        } else {
+                            missingTLD.put(asciiTld, unicodeTld + " " + comment);
+                            if (generateUnicodeTlds) {
+                                missingTLD.put(unicodeTld, asciiTld + " " + comment);
+                            }
+                        }
+                    } else {
+                        System.err.println("Expected to find HTML info for " + asciiTld);
+                    }
+                }
+                ianaTlds.add(asciiTld);
+                // Don't merge these conditions; generateUnicodeTlds is final so needs to be separate to avoid a warning
+                if (generateUnicodeTlds && !unicodeTld.equals(asciiTld)) {
+                    ianaTlds.add(unicodeTld);
+                }
+            }
+        }
+        br.close();
+        // List html entries not in TLD text list
+        for (final String key : new TreeMap<>(htmlInfo).keySet()) {
+            if (!ianaTlds.contains(key)) {
+                if (isNotInRootZone(key)) {
+                    System.out.println("INFO: HTML entry not yet in root zone: " + key);
+                } else {
+                    System.err.println("WARN: Expected to find text entry for html: " + key);
+                }
+            }
+        }
+        if (!missingTLD.isEmpty()) {
+            printMap(header, missingTLD, "GENERIC_TLDS");
+        }
+        if (!missingCC.isEmpty()) {
+            printMap(header, missingCC, "COUNTRY_CODE_TLDS");
+        }
+        // Check if internal tables contain any additional entries
+        isInIanaList("INFRASTRUCTURE_TLDS", ianaTlds);
+        isInIanaList("COUNTRY_CODE_TLDS", ianaTlds);
+        isInIanaList("GENERIC_TLDS", ianaTlds);
+        // Don't check local TLDS isInIanaList("LOCAL_TLDS", ianaTlds);
+        System.out.println("Finished checks");
+    }
+
+    private static void printMap(final String header, final Map<String, String> map, final String string) {
+        System.out.println("Entries missing from " + string + " List\n");
+        if (header != null) {
+            System.out.println("        // Taken from " + header);
+        }
+        for (final Entry<String, String> me : map.entrySet()) {
+            System.out.println("        \"" + me.getKey() + "\", // " + me.getValue());
+        }
+        System.out.println("\nDone");
+    }
+
+    private DomainValidator validator;
+
+    @BeforeEach
+    public void setUp() {
+        validator = DomainValidator.getInstance();
+    }
+
+    // Check array is sorted and is lower-case
+    @Test
+    public void test_COUNTRY_CODE_TLDS_sortedAndLowerCase() throws Exception {
+        final boolean sorted = isSortedLowerCase("COUNTRY_CODE_TLDS");
+        assertTrue(sorted);
+    }
+
+    // Check array is sorted and is lower-case
+    @Test
+    public void test_GENERIC_TLDS_sortedAndLowerCase() throws Exception {
+        final boolean sorted = isSortedLowerCase("GENERIC_TLDS");
+        assertTrue(sorted);
+    }
+
+    // Check array is sorted and is lower-case
+    @Test
+    public void test_INFRASTRUCTURE_TLDS_sortedAndLowerCase() throws Exception {
+        final boolean sorted = isSortedLowerCase("INFRASTRUCTURE_TLDS");
+        assertTrue(sorted);
+    }
+
+    // Check array is sorted and is lower-case
+    @Test
+    public void test_LOCAL_TLDS_sortedAndLowerCase() throws Exception {
+        final boolean sorted = isSortedLowerCase("LOCAL_TLDS");
+        assertTrue(sorted);
+    }
+
+    @Test
+    public void testAllowLocal() {
+        final DomainValidator noLocal = DomainValidator.getInstance(false);
+        final DomainValidator allowLocal = DomainValidator.getInstance(true);
+
+        // Default is false, and should use singletons
+        assertEquals(noLocal, validator);
+
+        // Default won't allow local
+        assertFalse(noLocal.isValid("localhost.localdomain"), "localhost.localdomain should validate");
+        assertFalse(noLocal.isValid("localhost"), "localhost should validate");
+
+        // But it may be requested
+        assertTrue(allowLocal.isValid("localhost.localdomain"), "localhost.localdomain should validate");
+        assertTrue(allowLocal.isValid("localhost"), "localhost should validate");
+        assertTrue(allowLocal.isValid("hostname"), "hostname should validate");
+        assertTrue(allowLocal.isValid("machinename"), "machinename should validate");
+
+        // Check the localhost one with a few others
+        assertTrue(allowLocal.isValid("apache.org"), "apache.org should validate");
+        assertFalse(allowLocal.isValid(" apache.org "), "domain name with spaces shouldn't validate");
+    }
+
+    @Test
+    public void testDomainNoDots() {// rfc1123
+        assertTrue(validator.isValidDomainSyntax("a"), "a (alpha) should validate");
+        assertTrue(validator.isValidDomainSyntax("9"), "9 (alphanum) should validate");
+        assertTrue(validator.isValidDomainSyntax("c-z"), "c-z (alpha - alpha) should validate");
+
+        assertFalse(validator.isValidDomainSyntax("c-"), "c- (alpha -) should fail");
+        assertFalse(validator.isValidDomainSyntax("-c"), "-c (- alpha) should fail");
+        assertFalse(validator.isValidDomainSyntax("-"), "- (-) should fail");
+    }
+
+    @Test
+    public void testEnumIsPublic() {
+        assertTrue(Modifier.isPublic(DomainValidator.ArrayType.class.getModifiers()));
+    }
+
+    @Test
+    public void testGetArray() {
+        assertNotNull(DomainValidator.getTLDEntries(ArrayType.COUNTRY_CODE_MINUS));
+        assertNotNull(DomainValidator.getTLDEntries(ArrayType.COUNTRY_CODE_PLUS));
+        assertNotNull(DomainValidator.getTLDEntries(ArrayType.GENERIC_MINUS));
+        assertNotNull(DomainValidator.getTLDEntries(ArrayType.GENERIC_PLUS));
+        assertNotNull(DomainValidator.getTLDEntries(ArrayType.LOCAL_MINUS));
+        assertNotNull(DomainValidator.getTLDEntries(ArrayType.LOCAL_PLUS));
+        assertNotNull(DomainValidator.getTLDEntries(ArrayType.COUNTRY_CODE_RO));
+        assertNotNull(DomainValidator.getTLDEntries(ArrayType.GENERIC_RO));
+        assertNotNull(DomainValidator.getTLDEntries(ArrayType.INFRASTRUCTURE_RO));
+        assertNotNull(DomainValidator.getTLDEntries(ArrayType.LOCAL_RO));
+    }
+
+    @Test
+    public void testIDN() {
+        assertTrue(validator.isValid("www.xn--bcher-kva.ch"), "b\u00fccher.ch in IDN should validate");
+    }
+
+    @Test
+    public void testIDNJava6OrLater() {
+        final String version = System.getProperty("java.version");
+        if (version.compareTo("1.6") < 0) {
+            System.out.println("Cannot run Unicode IDN tests");
+            return; // Cannot run the test
+        } // xn--d1abbgf6aiiy.xn--p1ai http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„
+        assertTrue(validator.isValid("www.b\u00fccher.ch"), "b\u00fccher.ch should validate");
+        assertTrue(validator.isValid("xn--d1abbgf6aiiy.xn--p1ai"), "xn--d1abbgf6aiiy.xn--p1ai should validate");
+        assertTrue(validator.isValid("ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„"), "ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„ should validate");
+        assertFalse(validator.isValid("www.\uFFFD.ch"), "www.\uFFFD.ch FFFD should fail");
+    }
+
+    @Test
+    public void testInvalidDomains() {
+        assertFalse(validator.isValid(".org"), "bare TLD .org shouldn't validate");
+        assertFalse(validator.isValid(" apache.org "), "domain name with spaces shouldn't validate");
+        assertFalse(validator.isValid("apa che.org"), "domain name containing spaces shouldn't validate");
+        assertFalse(validator.isValid("-testdomain.name"), "domain name starting with dash shouldn't validate");
+        assertFalse(validator.isValid("testdomain-.name"), "domain name ending with dash shouldn't validate");
+        assertFalse(validator.isValid("---c.com"), "domain name starting with multiple dashes shouldn't validate");
+        assertFalse(validator.isValid("c--.com"), "domain name ending with multiple dashes shouldn't validate");
+        assertFalse(validator.isValid("apache.rog"), "domain name with invalid TLD shouldn't validate");
+
+        assertFalse(validator.isValid("http://www.apache.org"), "URL shouldn't validate");
+        assertFalse(validator.isValid(" "), "Empty string shouldn't validate as domain name");
+        assertFalse(validator.isValid(null), "Null shouldn't validate as domain name");
+    }
+
+    // Check if IDN.toASCII is broken or not
+    @Test
+    public void testIsIDNtoASCIIBroken() {
+        System.out.println(">>DomainValidatorTest.testIsIDNtoASCIIBroken()");
+        final String input = ".";
+        final boolean ok = input.equals(IDN.toASCII(input));
+        System.out.println("IDN.toASCII is " + (ok ? "OK" : "BROKEN"));
+        final String[] props = { "java.version", // Java Runtime Environment version
+                "java.vendor", // Java Runtime Environment vendor
+                "java.vm.specification.version", // Java Virtual Machine specification version
+                "java.vm.specification.vendor", // Java Virtual Machine specification vendor
+                "java.vm.specification.name", // Java Virtual Machine specification name
+                "java.vm.version", // Java Virtual Machine implementation version
+                "java.vm.vendor", // Java Virtual Machine implementation vendor
+                "java.vm.name", // Java Virtual Machine implementation name
+                "java.specification.version", // Java Runtime Environment specification version
+                "java.specification.vendor", // Java Runtime Environment specification vendor
+                "java.specification.name", // Java Runtime Environment specification name
+                "java.class.version", // Java class format version number
+        };
+        for (final String t : props) {
+            System.out.println(t + "=" + System.getProperty(t));
+        }
+        System.out.println("<<DomainValidatorTest.testIsIDNtoASCIIBroken()");
+        assertTrue(true); // dummy assertion to satisfy lint
+    }
+
+    // RFC2396: domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
+    @Test
+    public void testRFC2396domainlabel() { // use fixed valid TLD
+        assertTrue(validator.isValid("a.ch"), "a.ch should validate");
+        assertTrue(validator.isValid("9.ch"), "9.ch should validate");
+        assertTrue(validator.isValid("az.ch"), "az.ch should validate");
+        assertTrue(validator.isValid("09.ch"), "09.ch should validate");
+        assertTrue(validator.isValid("9-1.ch"), "9-1.ch should validate");
+        assertFalse(validator.isValid("91-.ch"), "91-.ch should not validate");
+        assertFalse(validator.isValid("-.ch"), "-.ch should not validate");
+    }
+
+    // RFC2396 toplabel = alpha | alpha *( alphanum | "-" ) alphanum
+    @Test
+    public void testRFC2396toplabel() {
+        // These tests use non-existent TLDs so currently need to use a package protected method
+        assertTrue(validator.isValidDomainSyntax("a.c"), "a.c (alpha) should validate");
+        assertTrue(validator.isValidDomainSyntax("a.cc"), "a.cc (alpha alpha) should validate");
+        assertTrue(validator.isValidDomainSyntax("a.c9"), "a.c9 (alpha alphanum) should validate");
+        assertTrue(validator.isValidDomainSyntax("a.c-9"), "a.c-9 (alpha - alphanum) should validate");
+        assertTrue(validator.isValidDomainSyntax("a.c-z"), "a.c-z (alpha - alpha) should validate");
+
+        assertFalse(validator.isValidDomainSyntax("a.9c"), "a.9c (alphanum alpha) should fail");
+        assertFalse(validator.isValidDomainSyntax("a.c-"), "a.c- (alpha -) should fail");
+        assertFalse(validator.isValidDomainSyntax("a.-"), "a.- (-) should fail");
+        assertFalse(validator.isValidDomainSyntax("a.-9"), "a.-9 (- alphanum) should fail");
+    }
+
+    @Test
+    public void testTopLevelDomains() {
+        // infrastructure TLDs
+        assertTrue(validator.isValidInfrastructureTld(".arpa"), ".arpa should validate as iTLD");
+        assertFalse(validator.isValidInfrastructureTld(".com"), ".com shouldn't validate as iTLD");
+
+        // generic TLDs
+        assertTrue(validator.isValidGenericTld(".name"), ".name should validate as gTLD");
+        assertFalse(validator.isValidGenericTld(".us"), ".us shouldn't validate as gTLD");
+
+        // country code TLDs
+        assertTrue(validator.isValidCountryCodeTld(".uk"), ".uk should validate as ccTLD");
+        assertFalse(validator.isValidCountryCodeTld(".org"), ".org shouldn't validate as ccTLD");
+
+        // case-insensitive
+        assertTrue(validator.isValidTld(".COM"), ".COM should validate as TLD");
+        assertTrue(validator.isValidTld(".BiZ"), ".BiZ should validate as TLD");
+
+        // corner cases
+        assertFalse(validator.isValid(".nope"), "invalid TLD shouldn't validate"); // TODO this is not guaranteed invalid forever
+        assertFalse(validator.isValid(""), "empty string shouldn't validate as TLD");
+        assertFalse(validator.isValid(null), "null shouldn't validate as TLD");
+    }
+
+    // Check that IDN.toASCII behaves as it should (when wrapped by DomainValidator.unicodeToASCII)
+    // Tests show that method incorrectly trims a trailing "." character
+    @Test
+    public void testUnicodeToASCII() {
+        final String[] asciidots = { "", ",", ".", // fails IDN.toASCII, but should pass wrapped version
+                "a.", // ditto
+                "a.b", "a..b", "a...b", ".a", "..a", };
+        for (final String s : asciidots) {
+            assertEquals(s, DomainValidator.unicodeToASCII(s));
+        }
+        // RFC3490 3.1. 1)
+//      Whenever dots are used as label separators, the following
+//      characters MUST be recognized as dots: U+002E (full stop), U+3002
+//      (ideographic full stop), U+FF0E (fullwidth full stop), U+FF61
+//      (halfwidth ideographic full stop).
+        final String otherDots[][] = { { "b\u3002", "b.", }, { "b\uFF0E", "b.", }, { "b\uFF61", "b.", }, { "\u3002", ".", }, { "\uFF0E", ".", },
+                { "\uFF61", ".", }, };
+        for (final String s[] : otherDots) {
+            assertEquals(s[1], DomainValidator.unicodeToASCII(s[0]));
+        }
+    }
+
+    @Test
+    public void testValidator297() {
+        assertTrue(validator.isValid("xn--d1abbgf6aiiy.xn--p1ai"), "xn--d1abbgf6aiiy.xn--p1ai should validate"); // This uses a valid TLD
+    }
+
+    // labels are a max of 63 chars and domains 253
+    @Test
+    public void testValidator306() {
+        final String longString = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789A";
+        assertEquals(63, longString.length()); // 26 * 2 + 11
+
+        assertTrue(validator.isValidDomainSyntax(longString + ".com"), "63 chars label should validate");
+        assertFalse(validator.isValidDomainSyntax(longString + "x.com"), "64 chars label should fail");
+
+        assertTrue(validator.isValidDomainSyntax("test." + longString), "63 chars TLD should validate");
+        assertFalse(validator.isValidDomainSyntax("test.x" + longString), "64 chars TLD should fail");
+
+        final String longDomain = longString + "." + longString + "." + longString + "." + longString.substring(0, 61);
+        assertEquals(253, longDomain.length());
+        assertTrue(validator.isValidDomainSyntax(longDomain), "253 chars domain should validate");
+        assertFalse(validator.isValidDomainSyntax(longDomain + "x"), "254 chars domain should fail");
+    }
+
+    @Test
+    public void testValidDomains() {
+        assertTrue(validator.isValid("apache.org"), "apache.org should validate");
+        assertTrue(validator.isValid("www.google.com"), "www.google.com should validate");
+
+        assertTrue(validator.isValid("test-domain.com"), "test-domain.com should validate");
+        assertTrue(validator.isValid("test---domain.com"), "test---domain.com should validate");
+        assertTrue(validator.isValid("test-d-o-m-ain.com"), "test-d-o-m-ain.com should validate");
+        assertTrue(validator.isValid("as.uk"), "two-letter domain label should validate");
+
+        assertTrue(validator.isValid("ApAchE.Org"), "case-insensitive ApAchE.Org should validate");
+
+        assertTrue(validator.isValid("z.com"), "single-character domain label should validate");
+
+        assertTrue(validator.isValid("i.have.an-example.domain.name"), "i.have.an-example.domain.name should validate");
+    }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/DoubleValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/DoubleValidatorTest.java
index cd93553..c055bd9 100644
--- a/src/test/java/org/apache/commons/validator/routines/DoubleValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/DoubleValidatorTest.java
@@ -16,26 +16,27 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.util.Locale;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Test Case for DoubleValidator.
  */
 public class DoubleValidatorTest extends AbstractNumberValidatorTest {
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public DoubleValidatorTest(final String name) {
-        super(name);
-    }
-
     @Override
-    protected void setUp() throws Exception {
+    @BeforeEach
+    protected void setUp() {
         super.setUp();
 
-        validator       = new DoubleValidator(false, 0);
+        validator = new DoubleValidator(false, 0);
         strictValidator = new DoubleValidator();
 
         testPattern = "#,###.#";
@@ -47,18 +48,18 @@
         minMinusOne = null;
 
         // testInvalidStrict()
-        invalidStrict = new String[] {null, "", "X", "X12", "12X", "1X2"};
+        invalidStrict = new String[] { null, "", "X", "X12", "12X", "1X2" };
 
         // testInvalidNotStrict()
-        invalid       = new String[] {null, "", "X", "X12"};
+        invalid = new String[] { null, "", "X", "X12" };
 
         // testValid()
-        testNumber    = Double.valueOf(1234.5);
-        testZero      = Double.valueOf(0);
-        validStrict          = new String[] {"0", "1234.5", "1,234.5"};
-        validStrictCompare   = new Number[] {testZero, testNumber, testNumber};
-        valid                = new String[] {"0", "1234.5", "1,234.5", "1,234.5", "1234.5X"};
-        validCompare         = new Number[] {testZero, testNumber, testNumber, testNumber, testNumber};
+        testNumber = Double.valueOf(1234.5);
+        testZero = Double.valueOf(0);
+        validStrict = new String[] { "0", "1234.5", "1,234.5" };
+        validStrictCompare = new Number[] { testZero, testNumber, testNumber };
+        valid = new String[] { "0", "1234.5", "1,234.5", "1,234.5", "1234.5X" };
+        validCompare = new Number[] { testZero, testNumber, testNumber, testNumber, testNumber };
 
         testStringUS = "1,234.5";
         testStringDE = "1.234,5";
@@ -66,50 +67,18 @@
         // Localized Pattern test
         localeValue = testStringDE;
         localePattern = "#.###,#";
-        testLocale    = Locale.GERMANY;
+        testLocale = Locale.GERMANY;
         localeExpected = testNumber;
 
     }
 
     /**
-     * Test DoubleValidator validate Methods
-     */
-    public void testDoubleValidatorMethods() {
-        final Locale locale     = Locale.GERMAN;
-        final String pattern    = "0,00,00";
-        final String patternVal = "1,23,45";
-        final String germanPatternVal = "1.23.45";
-        final String localeVal  = "12.345";
-        final String defaultVal = "12,345";
-        final String XXXX    = "XXXX";
-        final Double expected = Double.valueOf(12345);
-        assertEquals("validate(A) default", expected, DoubleValidator.getInstance().validate(defaultVal));
-        assertEquals("validate(A) locale ", expected, DoubleValidator.getInstance().validate(localeVal, locale));
-        assertEquals("validate(A) pattern", expected, DoubleValidator.getInstance().validate(patternVal, pattern));
-        assertEquals("validate(A) both",    expected, DoubleValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertTrue("isValid(A) default", DoubleValidator.getInstance().isValid(defaultVal));
-        assertTrue("isValid(A) locale ", DoubleValidator.getInstance().isValid(localeVal, locale));
-        assertTrue("isValid(A) pattern", DoubleValidator.getInstance().isValid(patternVal, pattern));
-        assertTrue("isValid(A) both",    DoubleValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertNull("validate(B) default", DoubleValidator.getInstance().validate(XXXX));
-        assertNull("validate(B) locale ", DoubleValidator.getInstance().validate(XXXX, locale));
-        assertNull("validate(B) pattern", DoubleValidator.getInstance().validate(XXXX, pattern));
-        assertNull("validate(B) both",    DoubleValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN));
-
-        assertFalse("isValid(B) default", DoubleValidator.getInstance().isValid(XXXX));
-        assertFalse("isValid(B) locale ", DoubleValidator.getInstance().isValid(XXXX, locale));
-        assertFalse("isValid(B) pattern", DoubleValidator.getInstance().isValid(XXXX, pattern));
-        assertFalse("isValid(B) both",    DoubleValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN));
-    }
-
-    /**
      * Test Double Range/Min/Max
      */
+    @Test
     public void testDoubleRangeMinMax() {
-        final DoubleValidator validator = (DoubleValidator)strictValidator;
-        final Double number9  = validator.validate("9", "#");
+        final DoubleValidator validator = (DoubleValidator) strictValidator;
+        final Double number9 = validator.validate("9", "#");
         final Double number10 = validator.validate("10", "#");
         final Double number11 = validator.validate("11", "#");
         final Double number19 = validator.validate("19", "#");
@@ -117,20 +86,54 @@
         final Double number21 = validator.validate("21", "#");
 
         // Test isInRange()
-        assertFalse("isInRange() < min",   validator.isInRange(number9,  10, 20));
-        assertTrue("isInRange() = min",    validator.isInRange(number10, 10, 20));
-        assertTrue("isInRange() in range", validator.isInRange(number11, 10, 20));
-        assertTrue("isInRange() = max",    validator.isInRange(number20, 10, 20));
-        assertFalse("isInRange() > max",   validator.isInRange(number21, 10, 20));
+        assertFalse(validator.isInRange(number9, 10, 20), "isInRange() < min");
+        assertTrue(validator.isInRange(number10, 10, 20), "isInRange() = min");
+        assertTrue(validator.isInRange(number11, 10, 20), "isInRange() in range");
+        assertTrue(validator.isInRange(number20, 10, 20), "isInRange() = max");
+        assertFalse(validator.isInRange(number21, 10, 20), "isInRange() > max");
 
         // Test minValue()
-        assertFalse("minValue() < min",    validator.minValue(number9,  10));
-        assertTrue("minValue() = min",     validator.minValue(number10, 10));
-        assertTrue("minValue() > min",     validator.minValue(number11, 10));
+        assertFalse(validator.minValue(number9, 10), "minValue() < min");
+        assertTrue(validator.minValue(number10, 10), "minValue() = min");
+        assertTrue(validator.minValue(number11, 10), "minValue() > min");
 
         // Test minValue()
-        assertTrue("maxValue() < max",     validator.maxValue(number19, 20));
-        assertTrue("maxValue() = max",     validator.maxValue(number20, 20));
-        assertFalse("maxValue() > max",    validator.maxValue(number21, 20));
+        assertTrue(validator.maxValue(number19, 20), "maxValue() < max");
+        assertTrue(validator.maxValue(number20, 20), "maxValue() = max");
+        assertFalse(validator.maxValue(number21, 20), "maxValue() > max");
+    }
+
+    /**
+     * Test DoubleValidator validate Methods
+     */
+    @Test
+    public void testDoubleValidatorMethods() {
+        final Locale locale = Locale.GERMAN;
+        final String pattern = "0,00,00";
+        final String patternVal = "1,23,45";
+        final String germanPatternVal = "1.23.45";
+        final String localeVal = "12.345";
+        final String defaultVal = "12,345";
+        final String XXXX = "XXXX";
+        final Double expected = Double.valueOf(12345);
+        assertEquals(expected, DoubleValidator.getInstance().validate(defaultVal), "validate(A) default");
+        assertEquals(expected, DoubleValidator.getInstance().validate(localeVal, locale), "validate(A) locale");
+        assertEquals(expected, DoubleValidator.getInstance().validate(patternVal, pattern), "validate(A) pattern");
+        assertEquals(expected, DoubleValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN), "validate(A) both");
+
+        assertTrue(DoubleValidator.getInstance().isValid(defaultVal), "isValid(A) default");
+        assertTrue(DoubleValidator.getInstance().isValid(localeVal, locale), "isValid(A) locale");
+        assertTrue(DoubleValidator.getInstance().isValid(patternVal, pattern), "isValid(A) pattern");
+        assertTrue(DoubleValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN), "isValid(A) both");
+
+        assertNull(DoubleValidator.getInstance().validate(XXXX), "validate(B) default");
+        assertNull(DoubleValidator.getInstance().validate(XXXX, locale), "validate(B) locale ");
+        assertNull(DoubleValidator.getInstance().validate(XXXX, pattern), "validate(B) pattern");
+        assertNull(DoubleValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN), "validate(B) both");
+
+        assertFalse(DoubleValidator.getInstance().isValid(XXXX), "isValid(B) default");
+        assertFalse(DoubleValidator.getInstance().isValid(XXXX, locale), "isValid(B) locale");
+        assertFalse(DoubleValidator.getInstance().isValid(XXXX, pattern), "isValid(B) pattern");
+        assertFalse(DoubleValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN), "isValid(B) both");
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/EmailValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/EmailValidatorTest.java
index 6c8071e..44194dd 100644
--- a/src/test/java/org/apache/commons/validator/routines/EmailValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/EmailValidatorTest.java
@@ -19,18 +19,18 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.Is.is;
 import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.commons.validator.ResultPair;
-import org.junit.Before;
-import org.junit.Ignore;
-import org.junit.Test;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
 
 /**
  * Performs Validation Test for e-mail validations.
@@ -38,383 +38,21 @@
 public class EmailValidatorTest {
 
     /**
-     * The key used to retrieve the set of validation
-     * rules from the xml file.
+     * The key used to retrieve the set of validation rules from the xml file.
      */
     protected static String FORM_KEY = "emailForm";
 
-   /**
-    * The key used to retrieve the validator action.
-    */
-   protected static String ACTION = "email";
-
-   private EmailValidator validator;
-
-   @Before
-   public void setUp() {
-        validator = EmailValidator.getInstance();
-   }
-
-   /**
-    * Tests the e-mail validation.
-    */
-    @Test
-    public void testEmail()  {
-       assertTrue(validator.isValid("jsmith@apache.org"));
-    }
-
-   /**
-    * Tests the email validation with numeric domains.
-    */
-    @Test
-    public void testEmailWithNumericAddress()  {
-        assertTrue(validator.isValid("someone@[216.109.118.76]"));
-        assertTrue(validator.isValid("someone@yahoo.com"));
-    }
-
     /**
-     * Tests the e-mail validation.
+     * The key used to retrieve the validator action.
      */
-    @Test
-    public void testEmailExtension()  {
-        assertTrue(validator.isValid("jsmith@apache.org"));
-
-        assertTrue(validator.isValid("jsmith@apache.com"));
-
-        assertTrue(validator.isValid("jsmith@apache.net"));
-
-        assertTrue(validator.isValid("jsmith@apache.info"));
-
-        assertFalse(validator.isValid("jsmith@apache."));
-
-        assertFalse(validator.isValid("jsmith@apache.c"));
-
-        assertTrue(validator.isValid("someone@yahoo.museum"));
-
-        assertFalse(validator.isValid("someone@yahoo.mu-seum"));
-    }
-
-   /**
-    * <p>Tests the e-mail validation with a dash in
-    * the address.</p>
-    */
-    @Test
-    public void testEmailWithDash()  {
-       assertTrue(validator.isValid("andy.noble@data-workshop.com"));
-
-       assertFalse(validator.isValid("andy-noble@data-workshop.-com"));
-
-       assertFalse(validator.isValid("andy-noble@data-workshop.c-om"));
-
-       assertFalse(validator.isValid("andy-noble@data-workshop.co-m"));
-   }
-
-   /**
-    * Tests the e-mail validation with a dot at the end of
-    * the address.
-    */
-    @Test
-    public void testEmailWithDotEnd()  {
-      assertFalse(validator.isValid("andy.noble@data-workshop.com."));
-   }
+    protected static String ACTION = "email";
 
     /**
-     * Tests the e-mail validation with an RCS-noncompliant character in
-     * the address.
-     */
-    @Test
-    public void testEmailWithBogusCharacter()  {
-
-        assertFalse(validator.isValid("andy.noble@\u008fdata-workshop.com"));
-
-        // The ' character is valid in an email username.
-        assertTrue(validator.isValid("andy.o'reilly@data-workshop.com"));
-
-        // But not in the domain name.
-        assertFalse(validator.isValid("andy@o'reilly.data-workshop.com"));
-
-        // The + character is valid in an email username.
-        assertTrue(validator.isValid("foo+bar@i.am.not.in.us.example.com"));
-
-        // But not in the domain name
-        assertFalse(validator.isValid("foo+bar@example+3.com"));
-
-        // Domains with only special characters aren't allowed (VALIDATOR-286)
-        assertFalse(validator.isValid("test@%*.com"));
-        assertFalse(validator.isValid("test@^&#.com"));
-
-    }
-
-    @Test
-    public void testVALIDATOR_315() {
-        assertFalse(validator.isValid("me@at&t.net"));
-        assertTrue(validator.isValid("me@att.net")); // Make sure TLD is not the cause of the failure
-    }
-
-    @Test
-    public void testVALIDATOR_278() {
-        assertFalse(validator.isValid("someone@-test.com"));// hostname starts with dash/hyphen
-        assertFalse(validator.isValid("someone@test-.com"));// hostname ends with dash/hyphen
-    }
-
-    @Test
-    public void testValidator235() {
-        final String version = System.getProperty("java.version");
-        if (version.compareTo("1.6") < 0) {
-            System.out.println("Cannot run Unicode IDN tests");
-            return; // Cannot run the test
-        }
-        assertTrue("xn--d1abbgf6aiiy.xn--p1ai should validate", validator.isValid("someone@xn--d1abbgf6aiiy.xn--p1ai"));
-        assertTrue("ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„ should validate", validator.isValid("someone@ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„"));
-        assertTrue("www.b\u00fccher.ch should validate", validator.isValid("someone@www.b\u00fccher.ch"));
-        assertFalse("www.\uFFFD.ch FFFD should fail", validator.isValid("someone@www.\uFFFD.ch"));
-        assertTrue("www.b\u00fccher.ch should validate", validator.isValid("someone@www.b\u00fccher.ch"));
-        assertFalse("www.\uFFFD.ch FFFD should fail", validator.isValid("someone@www.\uFFFD.ch"));
-    }
-
-    /**
-    * Tests the email validation with commas.
-    */
-    @Test
-    public void testEmailWithCommas()  {
-        assertFalse(validator.isValid("joeblow@apa,che.org"));
-
-        assertFalse(validator.isValid("joeblow@apache.o,rg"));
-
-        assertFalse(validator.isValid("joeblow@apache,org"));
-
-    }
-
-   /**
-    * Tests the email validation with spaces.
-    */
-    @Test
-    public void testEmailWithSpaces()  {
-        assertFalse(validator.isValid("joeblow @apache.org"));
-
-        assertFalse(validator.isValid("joeblow@ apache.org"));
-
-        assertFalse(validator.isValid(" joeblow@apache.org"));
-
-        assertFalse(validator.isValid("joeblow@apache.org "));
-
-        assertFalse(validator.isValid("joe blow@apache.org "));
-
-        assertFalse(validator.isValid("joeblow@apa che.org "));
-
-        assertTrue(validator.isValid("\"joeblow \"@apache.org"));
-
-        assertTrue(validator.isValid("\" joeblow\"@apache.org"));
-
-        assertTrue(validator.isValid("\" joe blow \"@apache.org"));
-
-    }
-
-   /**
-    * Tests the email validation with ascii control characters.
-    * (i.e. Ascii chars 0 - 31 and 127)
-    */
-    @Test
-    public void testEmailWithControlChars()  {
-        for (char c = 0; c < 32; c++) {
-            assertFalse("Test control char " + ((int)c), validator.isValid("foo" + c + "bar@domain.com"));
-        }
-        assertFalse("Test control char 127", validator.isValid("foo" + ((char)127) + "bar@domain.com"));
-    }
-
-    /**
-     * Test that @localhost and @localhost.localdomain
-     *  addresses are declared as valid when requested.
-     */
-    @Test
-    public void testEmailLocalhost() {
-       // Check the default is not to allow
-       final EmailValidator noLocal = EmailValidator.getInstance(false);
-       final EmailValidator allowLocal = EmailValidator.getInstance(true);
-       assertEquals(validator, noLocal);
-
-       // Depends on the validator
-       assertTrue(
-             "@localhost.localdomain should be accepted but wasn't",
-             allowLocal.isValid("joe@localhost.localdomain")
-       );
-       assertTrue(
-             "@localhost should be accepted but wasn't",
-             allowLocal.isValid("joe@localhost")
-       );
-
-       assertFalse(
-             "@localhost.localdomain should be accepted but wasn't",
-             noLocal.isValid("joe@localhost.localdomain")
-       );
-       assertFalse(
-             "@localhost should be accepted but wasn't",
-             noLocal.isValid("joe@localhost")
-       );
-    }
-
-    /**
-     * VALIDATOR-296 - A / or a ! is valid in the user part,
-     *  but not in the domain part
-     */
-    @Test
-    public void testEmailWithSlashes() {
-       assertTrue(
-             "/ and ! valid in username",
-             validator.isValid("joe!/blow@apache.org")
-       );
-       assertFalse(
-             "/ not valid in domain",
-             validator.isValid("joe@ap/ache.org")
-       );
-       assertFalse(
-             "! not valid in domain",
-             validator.isValid("joe@apac!he.org")
-       );
-    }
-
-    /**
-     * Write this test according to parts of RFC, as opposed to the type of character
-     * that is being tested.
-     */
-    @Test
-    public void testEmailUserName()  {
-
-        assertTrue(validator.isValid("joe1blow@apache.org"));
-
-        assertTrue(validator.isValid("joe$blow@apache.org"));
-
-        assertTrue(validator.isValid("joe-@apache.org"));
-
-        assertTrue(validator.isValid("joe_@apache.org"));
-
-        assertTrue(validator.isValid("joe+@apache.org")); // + is valid unquoted
-
-        assertTrue(validator.isValid("joe!@apache.org")); // ! is valid unquoted
-
-        assertTrue(validator.isValid("joe*@apache.org")); // * is valid unquoted
-
-        assertTrue(validator.isValid("joe'@apache.org")); // ' is valid unquoted
-
-        assertTrue(validator.isValid("joe%45@apache.org")); // % is valid unquoted
-
-        assertTrue(validator.isValid("joe?@apache.org")); // ? is valid unquoted
-
-        assertTrue(validator.isValid("joe&@apache.org")); // & ditto
-
-        assertTrue(validator.isValid("joe=@apache.org")); // = ditto
-
-        assertTrue(validator.isValid("+joe@apache.org")); // + is valid unquoted
-
-        assertTrue(validator.isValid("!joe@apache.org")); // ! is valid unquoted
-
-        assertTrue(validator.isValid("*joe@apache.org")); // * is valid unquoted
-
-        assertTrue(validator.isValid("'joe@apache.org")); // ' is valid unquoted
-
-        assertTrue(validator.isValid("%joe45@apache.org")); // % is valid unquoted
-
-        assertTrue(validator.isValid("?joe@apache.org")); // ? is valid unquoted
-
-        assertTrue(validator.isValid("&joe@apache.org")); // & ditto
-
-        assertTrue(validator.isValid("=joe@apache.org")); // = ditto
-
-        assertTrue(validator.isValid("+@apache.org")); // + is valid unquoted
-
-        assertTrue(validator.isValid("!@apache.org")); // ! is valid unquoted
-
-        assertTrue(validator.isValid("*@apache.org")); // * is valid unquoted
-
-        assertTrue(validator.isValid("'@apache.org")); // ' is valid unquoted
-
-        assertTrue(validator.isValid("%@apache.org")); // % is valid unquoted
-
-        assertTrue(validator.isValid("?@apache.org")); // ? is valid unquoted
-
-        assertTrue(validator.isValid("&@apache.org")); // & ditto
-
-        assertTrue(validator.isValid("=@apache.org")); // = ditto
-
-
-        //UnQuoted Special characters are invalid
-
-        assertFalse(validator.isValid("joe.@apache.org")); // . not allowed at end of local part
-
-        assertFalse(validator.isValid(".joe@apache.org")); // . not allowed at start of local part
-
-        assertFalse(validator.isValid(".@apache.org")); // . not allowed alone
-
-        assertTrue(validator.isValid("joe.ok@apache.org")); // . allowed embedded
-
-        assertFalse(validator.isValid("joe..ok@apache.org")); // .. not allowed embedded
-
-        assertFalse(validator.isValid("..@apache.org")); // .. not allowed alone
-
-        assertFalse(validator.isValid("joe(@apache.org"));
-
-        assertFalse(validator.isValid("joe)@apache.org"));
-
-        assertFalse(validator.isValid("joe,@apache.org"));
-
-        assertFalse(validator.isValid("joe;@apache.org"));
-
-
-        //Quoted Special characters are valid
-        assertTrue(validator.isValid("\"joe.\"@apache.org"));
-
-        assertTrue(validator.isValid("\".joe\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe+\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe@\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe!\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe*\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe'\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe(\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe)\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe,\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe%45\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe;\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe?\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe&\"@apache.org"));
-
-        assertTrue(validator.isValid("\"joe=\"@apache.org"));
-
-        assertTrue(validator.isValid("\"..\"@apache.org"));
-
-        // escaped quote character valid in quoted string
-        assertTrue(validator.isValid("\"john\\\"doe\"@apache.org"));
-
-        assertTrue(validator.isValid("john56789.john56789.john56789.john56789.john56789.john56789.john@example.com"));
-
-        assertFalse(validator.isValid("john56789.john56789.john56789.john56789.john56789.john56789.john5@example.com"));
-
-        assertTrue(validator.isValid("\\>escape\\\\special\\^characters\\<@example.com"));
-
-        assertTrue(validator.isValid("Abc\\@def@example.com"));
-
-        assertFalse(validator.isValid("Abc@def@example.com"));
-
-        assertTrue(validator.isValid("space\\ monkey@example.com"));
-    }
-
-    /**
-     * These test values derive directly from RFC 822 &
-     * Mail::RFC822::Address & RFC::RFC822::Address perl test.pl
-     * For traceability don't combine these test values with other tests.
+     * These test values derive directly from RFC 822 & Mail::RFC822::Address & RFC::RFC822::Address perl test.pl For traceability don't combine these test
+     * values with other tests.
      */
     private static final ResultPair[] testEmailFromPerl = {
+        // @formatter:off
         new ResultPair("abigail@example.com", true),
         new ResultPair("abigail@example.com ", true),
         new ResultPair(" abigail@example.com", true),
@@ -483,33 +121,384 @@
         new ResultPair("@example.com", false),
         new ResultPair("phrase: abigail@example.com abigail@example.com ;", false),
         new ResultPair("invalidīŋŊchar@example.com", false)
+    // @formatter:on
     };
 
+    public static void main(final String[] args) {
+        final EmailValidator validator = EmailValidator.getInstance();
+        for (final String arg : args) {
+            System.out.printf("%s: %s%n", arg, validator.isValid(arg));
+        }
+    }
+
+    private EmailValidator validator;
+
+    @BeforeEach
+    public void setUp() {
+        validator = EmailValidator.getInstance();
+    }
+
     /**
-     * Write this test based on perl Mail::RFC822::Address
-     * which takes its example email address directly from RFC822
-     *
-     * This test fails so disable it
-     * The real solution is to fix the email parsing.
+     * Tests the e-mail validation.
      */
-    @Ignore("VALIDATOR-267")
     @Test
-    public void testEmailFromPerl()  {
+    public void testEmail() {
+        assertTrue(validator.isValid("jsmith@apache.org"));
+    }
+
+    /**
+     * Tests the e-mail validation with a user at a TLD
+     *
+     * https://tools.ietf.org/html/rfc5321#section-2.3.5 (In the case of a top-level domain used by itself in an email address, a single string is used without
+     * any dots)
+     */
+    @Test
+    public void testEmailAtTLD() {
+        final EmailValidator val = EmailValidator.getInstance(false, true);
+        assertTrue(val.isValid("test@com"));
+    }
+
+    /**
+     * Tests the e-mail validation.
+     */
+    @Test
+    public void testEmailExtension() {
+        assertTrue(validator.isValid("jsmith@apache.org"));
+
+        assertTrue(validator.isValid("jsmith@apache.com"));
+
+        assertTrue(validator.isValid("jsmith@apache.net"));
+
+        assertTrue(validator.isValid("jsmith@apache.info"));
+
+        assertFalse(validator.isValid("jsmith@apache."));
+
+        assertFalse(validator.isValid("jsmith@apache.c"));
+
+        assertTrue(validator.isValid("someone@yahoo.museum"));
+
+        assertFalse(validator.isValid("someone@yahoo.mu-seum"));
+    }
+
+    /**
+     * Write this test based on perl Mail::RFC822::Address which takes its example email address directly from RFC822
+     *
+     * This test fails so disable it The real solution is to fix the email parsing.
+     */
+    @Disabled("VALIDATOR-267")
+    @Test
+    public void testEmailFromPerl() {
         int errors = 0;
         for (final ResultPair element : testEmailFromPerl) {
             final String item = element.item;
-            final boolean exp =  element.valid;
+            final boolean exp = element.valid;
             final boolean act = validator.isValid(item);
             if (act != exp) {
                 System.out.printf("%s: expected %s actual %s%n", item, exp, act);
                 errors += 1;
             }
         }
-        assertEquals("Expected 0 errors", 0, errors);
+        assertEquals(0, errors, "Expected 0 errors");
+    }
+
+    /**
+     * Test that @localhost and @localhost.localdomain addresses are declared as valid when requested.
+     */
+    @Test
+    public void testEmailLocalhost() {
+        // Check the default is not to allow
+        final EmailValidator noLocal = EmailValidator.getInstance(false);
+        final EmailValidator allowLocal = EmailValidator.getInstance(true);
+        assertEquals(validator, noLocal);
+
+        // Depends on the validator
+        assertTrue(allowLocal.isValid("joe@localhost.localdomain"), "@localhost.localdomain should be accepted but wasn't");
+        assertTrue(allowLocal.isValid("joe@localhost"), "@localhost should be accepted but wasn't");
+
+        assertFalse(noLocal.isValid("joe@localhost.localdomain"), "@localhost.localdomain should be accepted but wasn't");
+        assertFalse(noLocal.isValid("joe@localhost"), "@localhost should be accepted but wasn't");
+    }
+
+    /**
+     * Write this test according to parts of RFC, as opposed to the type of character that is being tested.
+     */
+    @Test
+    public void testEmailUserName() {
+
+        assertTrue(validator.isValid("joe1blow@apache.org"));
+
+        assertTrue(validator.isValid("joe$blow@apache.org"));
+
+        assertTrue(validator.isValid("joe-@apache.org"));
+
+        assertTrue(validator.isValid("joe_@apache.org"));
+
+        assertTrue(validator.isValid("joe+@apache.org")); // + is valid unquoted
+
+        assertTrue(validator.isValid("joe!@apache.org")); // ! is valid unquoted
+
+        assertTrue(validator.isValid("joe*@apache.org")); // * is valid unquoted
+
+        assertTrue(validator.isValid("joe'@apache.org")); // ' is valid unquoted
+
+        assertTrue(validator.isValid("joe%45@apache.org")); // % is valid unquoted
+
+        assertTrue(validator.isValid("joe?@apache.org")); // ? is valid unquoted
+
+        assertTrue(validator.isValid("joe&@apache.org")); // & ditto
+
+        assertTrue(validator.isValid("joe=@apache.org")); // = ditto
+
+        assertTrue(validator.isValid("+joe@apache.org")); // + is valid unquoted
+
+        assertTrue(validator.isValid("!joe@apache.org")); // ! is valid unquoted
+
+        assertTrue(validator.isValid("*joe@apache.org")); // * is valid unquoted
+
+        assertTrue(validator.isValid("'joe@apache.org")); // ' is valid unquoted
+
+        assertTrue(validator.isValid("%joe45@apache.org")); // % is valid unquoted
+
+        assertTrue(validator.isValid("?joe@apache.org")); // ? is valid unquoted
+
+        assertTrue(validator.isValid("&joe@apache.org")); // & ditto
+
+        assertTrue(validator.isValid("=joe@apache.org")); // = ditto
+
+        assertTrue(validator.isValid("+@apache.org")); // + is valid unquoted
+
+        assertTrue(validator.isValid("!@apache.org")); // ! is valid unquoted
+
+        assertTrue(validator.isValid("*@apache.org")); // * is valid unquoted
+
+        assertTrue(validator.isValid("'@apache.org")); // ' is valid unquoted
+
+        assertTrue(validator.isValid("%@apache.org")); // % is valid unquoted
+
+        assertTrue(validator.isValid("?@apache.org")); // ? is valid unquoted
+
+        assertTrue(validator.isValid("&@apache.org")); // & ditto
+
+        assertTrue(validator.isValid("=@apache.org")); // = ditto
+
+        // UnQuoted Special characters are invalid
+
+        assertFalse(validator.isValid("joe.@apache.org")); // . not allowed at end of local part
+
+        assertFalse(validator.isValid(".joe@apache.org")); // . not allowed at start of local part
+
+        assertFalse(validator.isValid(".@apache.org")); // . not allowed alone
+
+        assertTrue(validator.isValid("joe.ok@apache.org")); // . allowed embedded
+
+        assertFalse(validator.isValid("joe..ok@apache.org")); // .. not allowed embedded
+
+        assertFalse(validator.isValid("..@apache.org")); // .. not allowed alone
+
+        assertFalse(validator.isValid("joe(@apache.org"));
+
+        assertFalse(validator.isValid("joe)@apache.org"));
+
+        assertFalse(validator.isValid("joe,@apache.org"));
+
+        assertFalse(validator.isValid("joe;@apache.org"));
+
+        // Quoted Special characters are valid
+        assertTrue(validator.isValid("\"joe.\"@apache.org"));
+
+        assertTrue(validator.isValid("\".joe\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe+\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe@\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe!\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe*\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe'\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe(\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe)\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe,\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe%45\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe;\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe?\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe&\"@apache.org"));
+
+        assertTrue(validator.isValid("\"joe=\"@apache.org"));
+
+        assertTrue(validator.isValid("\"..\"@apache.org"));
+
+        // escaped quote character valid in quoted string
+        assertTrue(validator.isValid("\"john\\\"doe\"@apache.org"));
+
+        assertTrue(validator.isValid("john56789.john56789.john56789.john56789.john56789.john56789.john@example.com"));
+
+        assertFalse(validator.isValid("john56789.john56789.john56789.john56789.john56789.john56789.john5@example.com"));
+
+        assertTrue(validator.isValid("\\>escape\\\\special\\^characters\\<@example.com"));
+
+        assertTrue(validator.isValid("Abc\\@def@example.com"));
+
+        assertFalse(validator.isValid("Abc@def@example.com"));
+
+        assertTrue(validator.isValid("space\\ monkey@example.com"));
+    }
+
+    /**
+     * Tests the e-mail validation with an RCS-noncompliant character in the address.
+     */
+    @Test
+    public void testEmailWithBogusCharacter() {
+
+        assertFalse(validator.isValid("andy.noble@\u008fdata-workshop.com"));
+
+        // The ' character is valid in an email username.
+        assertTrue(validator.isValid("andy.o'reilly@data-workshop.com"));
+
+        // But not in the domain name.
+        assertFalse(validator.isValid("andy@o'reilly.data-workshop.com"));
+
+        // The + character is valid in an email username.
+        assertTrue(validator.isValid("foo+bar@i.am.not.in.us.example.com"));
+
+        // But not in the domain name
+        assertFalse(validator.isValid("foo+bar@example+3.com"));
+
+        // Domains with only special characters aren't allowed (VALIDATOR-286)
+        assertFalse(validator.isValid("test@%*.com"));
+        assertFalse(validator.isValid("test@^&#.com"));
+
+    }
+
+    /**
+     * Tests the email validation with commas.
+     */
+    @Test
+    public void testEmailWithCommas() {
+        assertFalse(validator.isValid("joeblow@apa,che.org"));
+
+        assertFalse(validator.isValid("joeblow@apache.o,rg"));
+
+        assertFalse(validator.isValid("joeblow@apache,org"));
+
+    }
+
+    /**
+     * Tests the email validation with ASCII control characters. (i.e. ASCII chars 0 - 31 and 127)
+     */
+    @Test
+    public void testEmailWithControlChars() {
+        for (char c = 0; c < 32; c++) {
+            assertFalse(validator.isValid("foo" + c + "bar@domain.com"), "Test control char " + (int) c);
+        }
+        assertFalse(validator.isValid("foo" + (char) 127 + "bar@domain.com"), "Test control char 127");
+    }
+
+    /**
+     * <p>
+     * Tests the e-mail validation with a dash in the address.
+     * </p>
+     */
+    @Test
+    public void testEmailWithDash() {
+        assertTrue(validator.isValid("andy.noble@data-workshop.com"));
+
+        assertFalse(validator.isValid("andy-noble@data-workshop.-com"));
+
+        assertFalse(validator.isValid("andy-noble@data-workshop.c-om"));
+
+        assertFalse(validator.isValid("andy-noble@data-workshop.co-m"));
+    }
+
+    /**
+     * Tests the e-mail validation with a dot at the end of the address.
+     */
+    @Test
+    public void testEmailWithDotEnd() {
+        assertFalse(validator.isValid("andy.noble@data-workshop.com."));
+    }
+
+    /**
+     * Tests the email validation with numeric domains.
+     */
+    @Test
+    public void testEmailWithNumericAddress() {
+        assertTrue(validator.isValid("someone@[216.109.118.76]"));
+        assertTrue(validator.isValid("someone@yahoo.com"));
+    }
+
+    /**
+     * VALIDATOR-296 - A / or a ! is valid in the user part, but not in the domain part
+     */
+    @Test
+    public void testEmailWithSlashes() {
+        assertTrue(validator.isValid("joe!/blow@apache.org"), "/ and ! valid in username");
+        assertFalse(validator.isValid("joe@ap/ache.org"), "/ not valid in domain");
+        assertFalse(validator.isValid("joe@apac!he.org"), "! not valid in domain");
+    }
+
+    /**
+     * Tests the email validation with spaces.
+     */
+    @Test
+    public void testEmailWithSpaces() {
+        assertFalse(validator.isValid("joeblow @apache.org"));
+
+        assertFalse(validator.isValid("joeblow@ apache.org"));
+
+        assertFalse(validator.isValid(" joeblow@apache.org"));
+
+        assertFalse(validator.isValid("joeblow@apache.org "));
+
+        assertFalse(validator.isValid("joe blow@apache.org "));
+
+        assertFalse(validator.isValid("joeblow@apa che.org "));
+
+        assertTrue(validator.isValid("\"joeblow \"@apache.org"));
+
+        assertTrue(validator.isValid("\" joeblow\"@apache.org"));
+
+        assertTrue(validator.isValid("\" joe blow \"@apache.org"));
+
     }
 
     @Test
-    public void testValidator293(){
+    public void testVALIDATOR_278() {
+        assertFalse(validator.isValid("someone@-test.com"));// hostname starts with dash/hyphen
+        assertFalse(validator.isValid("someone@test-.com"));// hostname ends with dash/hyphen
+    }
+
+    @Test
+    public void testVALIDATOR_315() {
+        assertFalse(validator.isValid("me@at&t.net"));
+        assertTrue(validator.isValid("me@att.net")); // Make sure TLD is not the cause of the failure
+    }
+
+    @Test
+    public void testValidator235() {
+        final String version = System.getProperty("java.version");
+        if (version.compareTo("1.6") < 0) {
+            System.out.println("Cannot run Unicode IDN tests");
+            return; // Cannot run the test
+        }
+        assertTrue(validator.isValid("someone@xn--d1abbgf6aiiy.xn--p1ai"), "xn--d1abbgf6aiiy.xn--p1ai should validate");
+        assertTrue(validator.isValid("someone@ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„"), "ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„ should validate");
+        assertTrue(validator.isValid("someone@www.b\u00fccher.ch"), "www.b\u00fccher.ch should validate");
+        assertFalse(validator.isValid("someone@www.\uFFFD.ch"), "www.\uFFFD.ch FFFD should fail");
+        assertTrue(validator.isValid("someone@www.b\u00fccher.ch"), "www.b\u00fccher.ch should validate");
+        assertFalse(validator.isValid("someone@www.\uFFFD.ch"), "www.\uFFFD.ch FFFD should fail");
+    }
+
+    @Test
+    public void testValidator293() {
         assertTrue(validator.isValid("abc-@abc.com"));
         assertTrue(validator.isValid("abc_@abc.com"));
         assertTrue(validator.isValid("abc-def@abc.com"));
@@ -518,77 +507,62 @@
     }
 
     @Test
-    public void testValidator365() {
-        assertFalse(validator.isValid(
-                "Loremipsumdolorsitametconsecteturadipiscingelit.Nullavitaeligulamattisrhoncusnuncegestasmattisleo."+
-                "Donecnonsapieninmagnatristiquedictumaacturpis.Fusceorciduifacilisisutsapieneuconsequatpharetralectus."+
-                "Quisqueenimestpulvinarutquamvitaeportamattisex.Nullamquismaurisplaceratconvallisjustoquisportamauris."+
-                "Innullalacusconvalliseufringillautvenenatissitametdiam.Maecenasluctusligulascelerisquepulvinarfeugiat."+
-                "Sedmolestienullaaliquetorciluctusidpharetranislfinibus.Suspendissemalesuadatinciduntduisitametportaarcusollicitudinnec."+
-                "Donecetmassamagna.Curabitururnadiampretiumveldignissimporttitorfringillaeuneque."+
-                "Duisantetelluspharetraidtinciduntinterdummolestiesitametfelis.Utquisquamsitametantesagittisdapibusacnonodio."+
-                "Namrutrummolestiediamidmattis.Cumsociisnatoquepenatibusetmagnisdisparturientmontesnasceturridiculusmus."+
-                "Morbiposueresedmetusacconsectetur.Etiamquisipsumvitaejustotempusmaximus.Sedultriciesplaceratvolutpat."+
-                "Integerlacuslectusmaximusacornarequissagittissitametjusto."+
-                "Cumsociisnatoquepenatibusetmagnisdisparturientmontesnasceturridiculusmus.Maecenasindictumpurussedrutrumex.Nullafacilisi."+
-                "Integerfinibusfinibusmietpharetranislfaucibusvel.Maecenasegetdolorlacinialobortisjustovelullamcorpersem."+
-                "Vivamusaliquetpurusidvariusornaresapienrisusrutrumnisitinciduntmollissemnequeidmetus."+
-                "Etiamquiseleifendpurus.Nuncfelisnuncscelerisqueiddignissimnecfinibusalibero."+
-                "Nuncsemperenimnequesitamethendreritpurusfacilisisac.Maurisdapibussemperfelisdignissimgravida."+
-                "Aeneanultricesblanditnequealiquamfinibusodioscelerisqueac.Aliquamnecmassaeumaurisfaucibusfringilla."+
-                "Etiamconsequatligulanisisitametaliquamnibhtemporquis.Nuncinterdumdignissimnullaatsodalesarcusagittiseu."+
-                "Proinpharetrametusneclacuspulvinarsedvolutpatliberoornare.Sedligulanislpulvinarnonlectuseublanditfacilisisante."+
-                "Sedmollisnislalacusauctorsuscipit.Inhachabitasseplateadictumst.Phasellussitametvelittemporvenenatisfeliseuegestasrisus."+
-                "Aliquameteratsitametnibhcommodofinibus.Morbiefficiturodiovelpulvinariaculis."+
-                "Aeneantemporipsummassaaconsecteturturpisfaucibusultrices.Praesentsodalesmaurisquisportafermentum."+
-                "Etiamnisinislvenenatisvelauctorutullamcorperinjusto.Proinvelligulaerat.Phasellusvestibulumgravidamassanonfeugiat."+
-                "Maecenaspharetraeuismodmetusegetefficitur.Suspendisseamet@gmail.com"));
-    }
-
-    /**
-     * Tests the e-mail validation with a user at a TLD
-     *
-     * http://tools.ietf.org/html/rfc5321#section-2.3.5
-     * (In the case of a top-level domain used by itself in an
-     * email address, a single string is used without any dots)
-     */
-    @Test
-    public void testEmailAtTLD() {
-        final EmailValidator val = EmailValidator.getInstance(false, true);
-        assertTrue(val.isValid("test@com"));
-    }
-
-    @Test
     public void testValidator359() {
         final EmailValidator val = EmailValidator.getInstance(false, true);
         assertFalse(val.isValid("test@.com"));
     }
 
     @Test
+    public void testValidator365() {
+        assertFalse(validator.isValid("Loremipsumdolorsitametconsecteturadipiscingelit.Nullavitaeligulamattisrhoncusnuncegestasmattisleo."
+                + "Donecnonsapieninmagnatristiquedictumaacturpis.Fusceorciduifacilisisutsapieneuconsequatpharetralectus."
+                + "Quisqueenimestpulvinarutquamvitaeportamattisex.Nullamquismaurisplaceratconvallisjustoquisportamauris."
+                + "Innullalacusconvalliseufringillautvenenatissitametdiam.Maecenasluctusligulascelerisquepulvinarfeugiat."
+                + "Sedmolestienullaaliquetorciluctusidpharetranislfinibus.Suspendissemalesuadatinciduntduisitametportaarcusollicitudinnec."
+                + "Donecetmassamagna.Curabitururnadiampretiumveldignissimporttitorfringillaeuneque."
+                + "Duisantetelluspharetraidtinciduntinterdummolestiesitametfelis.Utquisquamsitametantesagittisdapibusacnonodio."
+                + "Namrutrummolestiediamidmattis.Cumsociisnatoquepenatibusetmagnisdisparturientmontesnasceturridiculusmus."
+                + "Morbiposueresedmetusacconsectetur.Etiamquisipsumvitaejustotempusmaximus.Sedultriciesplaceratvolutpat."
+                + "Integerlacuslectusmaximusacornarequissagittissitametjusto."
+                + "Cumsociisnatoquepenatibusetmagnisdisparturientmontesnasceturridiculusmus.Maecenasindictumpurussedrutrumex.Nullafacilisi."
+                + "Integerfinibusfinibusmietpharetranislfaucibusvel.Maecenasegetdolorlacinialobortisjustovelullamcorpersem."
+                + "Vivamusaliquetpurusidvariusornaresapienrisusrutrumnisitinciduntmollissemnequeidmetus."
+                + "Etiamquiseleifendpurus.Nuncfelisnuncscelerisqueiddignissimnecfinibusalibero."
+                + "Nuncsemperenimnequesitamethendreritpurusfacilisisac.Maurisdapibussemperfelisdignissimgravida."
+                + "Aeneanultricesblanditnequealiquamfinibusodioscelerisqueac.Aliquamnecmassaeumaurisfaucibusfringilla."
+                + "Etiamconsequatligulanisisitametaliquamnibhtemporquis.Nuncinterdumdignissimnullaatsodalesarcusagittiseu."
+                + "Proinpharetrametusneclacuspulvinarsedvolutpatliberoornare.Sedligulanislpulvinarnonlectuseublanditfacilisisante."
+                + "Sedmollisnislalacusauctorsuscipit.Inhachabitasseplateadictumst.Phasellussitametvelittemporvenenatisfeliseuegestasrisus."
+                + "Aliquameteratsitametnibhcommodofinibus.Morbiefficiturodiovelpulvinariaculis."
+                + "Aeneantemporipsummassaaconsecteturturpisfaucibusultrices.Praesentsodalesmaurisquisportafermentum."
+                + "Etiamnisinislvenenatisvelauctorutullamcorperinjusto.Proinvelligulaerat.Phasellusvestibulumgravidamassanonfeugiat."
+                + "Maecenaspharetraeuismodmetusegetefficitur.Suspendisseamet@gmail.com"));
+    }
+
+    @Test
     public void testValidator374() {
         assertTrue(validator.isValid("abc@school.school"));
     }
 
     @Test
     public void testValidator473_1() { // reject null DomainValidator
-        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
-                new EmailValidator(false, false, null));
+        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> new EmailValidator(false, false, null));
         assertThat(thrown.getMessage(), is(equalTo("DomainValidator cannot be null")));
     }
 
     @Test
     public void testValidator473_2() { // reject null DomainValidator with mismatched allowLocal
         final List<DomainValidator.Item> items = new ArrayList<>();
-        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
-                new EmailValidator(false, false, DomainValidator.getInstance(true, items)));
+        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
+                () -> new EmailValidator(false, false, DomainValidator.getInstance(true, items)));
         assertThat(thrown.getMessage(), is(equalTo("DomainValidator must agree with allowLocal setting")));
     }
 
     @Test
     public void testValidator473_3() { // reject null DomainValidator with mismatched allowLocal
         final List<DomainValidator.Item> items = new ArrayList<>();
-        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
-                new EmailValidator(true, false, DomainValidator.getInstance(false, items)));
+        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
+                () -> new EmailValidator(true, false, DomainValidator.getInstance(false, items)));
         assertThat(thrown.getMessage(), is(equalTo("DomainValidator must agree with allowLocal setting")));
     }
 
@@ -600,11 +574,4 @@
         final EmailValidator val = new EmailValidator(true, false, DomainValidator.getInstance(true, items));
         assertTrue(val.isValidDomain("test.local"));
     }
-
-    public static void main(final String[] args) {
-        final EmailValidator validator = EmailValidator.getInstance();
-        for(final String arg : args) {
-            System.out.printf("%s: %s%n", arg, validator.isValid(arg));
-        }
-    }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/FloatValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/FloatValidatorTest.java
index 8c13899..3274b60 100644
--- a/src/test/java/org/apache/commons/validator/routines/FloatValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/FloatValidatorTest.java
@@ -16,27 +16,28 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.text.DecimalFormat;
 import java.util.Locale;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Test Case for FloatValidator.
  */
 public class FloatValidatorTest extends AbstractNumberValidatorTest {
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public FloatValidatorTest(final String name) {
-        super(name);
-    }
-
     @Override
-    protected void setUp() throws Exception {
+    @BeforeEach
+    protected void setUp() {
         super.setUp();
 
-        validator       = new FloatValidator(false, 0);
+        validator = new FloatValidator(false, 0);
         strictValidator = new FloatValidator();
 
         testPattern = "#,###.#";
@@ -48,18 +49,18 @@
         minMinusOne = Double.valueOf(min.doubleValue() * 10);
 
         // testInvalidStrict()
-        invalidStrict = new String[] {null, "", "X", "X12", "12X", "1X2"};
+        invalidStrict = new String[] { null, "", "X", "X12", "12X", "1X2" };
 
         // testInvalidNotStrict()
-        invalid       = new String[] {null, "", "X", "X12"};
+        invalid = new String[] { null, "", "X", "X12" };
 
         // testValid()
-        testNumber    = Float.valueOf(1234.5f);
-        testZero      = Float.valueOf(0);
-        validStrict          = new String[] {"0", "1234.5", "1,234.5"};
-        validStrictCompare   = new Number[] {testZero, testNumber, testNumber};
-        valid                = new String[] {"0", "1234.5", "1,234.5", "1,234.5", "1234.5X"};
-        validCompare         = new Number[] {testZero, testNumber, testNumber, testNumber, testNumber};
+        testNumber = Float.valueOf(1234.5f);
+        testZero = Float.valueOf(0);
+        validStrict = new String[] { "0", "1234.5", "1,234.5" };
+        validStrictCompare = new Number[] { testZero, testNumber, testNumber };
+        valid = new String[] { "0", "1234.5", "1,234.5", "1,234.5", "1234.5X" };
+        validCompare = new Number[] { testZero, testNumber, testNumber, testNumber, testNumber };
 
         testStringUS = "1,234.5";
         testStringDE = "1.234,5";
@@ -67,79 +68,18 @@
         // Localized Pattern test
         localeValue = testStringDE;
         localePattern = "#.###,#";
-        testLocale    = Locale.GERMANY;
+        testLocale = Locale.GERMANY;
         localeExpected = testNumber;
 
     }
 
     /**
-     * Test FloatValidator validate Methods
-     */
-    public void testFloatValidatorMethods() {
-        final Locale locale     = Locale.GERMAN;
-        final String pattern    = "0,00,00";
-        final String patternVal = "1,23,45";
-        final String localeVal  = "12.345";
-        final String germanPatternVal = "1.23.45";
-        final String defaultVal = "12,345";
-        final String XXXX    = "XXXX";
-        final Float expected = Float.valueOf(12345);
-        assertEquals("validate(A) default", expected, FloatValidator.getInstance().validate(defaultVal));
-        assertEquals("validate(A) locale ", expected, FloatValidator.getInstance().validate(localeVal, locale));
-        assertEquals("validate(A) pattern", expected, FloatValidator.getInstance().validate(patternVal, pattern));
-        assertEquals("validate(A) both",    expected, FloatValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertTrue("isValid(A) default", FloatValidator.getInstance().isValid(defaultVal));
-        assertTrue("isValid(A) locale ", FloatValidator.getInstance().isValid(localeVal, locale));
-        assertTrue("isValid(A) pattern", FloatValidator.getInstance().isValid(patternVal, pattern));
-        assertTrue("isValid(A) both",    FloatValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertNull("validate(B) default", FloatValidator.getInstance().validate(XXXX));
-        assertNull("validate(B) locale ", FloatValidator.getInstance().validate(XXXX, locale));
-        assertNull("validate(B) pattern", FloatValidator.getInstance().validate(XXXX, pattern));
-        assertNull("validate(B) both",    FloatValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN));
-
-        assertFalse("isValid(B) default", FloatValidator.getInstance().isValid(XXXX));
-        assertFalse("isValid(B) locale ", FloatValidator.getInstance().isValid(XXXX, locale));
-        assertFalse("isValid(B) pattern", FloatValidator.getInstance().isValid(XXXX, pattern));
-        assertFalse("isValid(B) both",    FloatValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN));
-    }
-
-    /**
-     * Test Float validation for values too small to handle.
-     * (slightly different from max/min which are the largest +ve/-ve
-     */
-    public void testFloatSmallestValues() {
-        final String pattern = "#.#################################################################";
-        final DecimalFormat fmt = new DecimalFormat(pattern);
-
-        // Validate Smallest +ve value
-        final Float smallestPositive  = Float.valueOf(Float.MIN_VALUE);
-        final String strSmallestPositive = fmt.format(smallestPositive);
-        assertEquals("Smallest +ve", smallestPositive, FloatValidator.getInstance().validate(strSmallestPositive, pattern));
-
-        // Validate Smallest -ve value
-        final Float smallestNegative  = Float.valueOf(Float.MIN_VALUE * -1);
-        final String strSmallestNegative = fmt.format(smallestNegative);
-        assertEquals("Smallest -ve", smallestNegative, FloatValidator.getInstance().validate(strSmallestNegative, pattern));
-
-        // Validate Too Small +ve
-        final Double tooSmallPositive = Double.valueOf(((double)Float.MIN_VALUE / (double)10));
-        final String strTooSmallPositive = fmt.format(tooSmallPositive);
-        assertFalse("Too small +ve", FloatValidator.getInstance().isValid(strTooSmallPositive, pattern));
-
-        // Validate Too Small -ve
-        final Double tooSmallNegative = Double.valueOf(tooSmallPositive.doubleValue() * -1);
-        final String strTooSmallNegative = fmt.format(tooSmallNegative);
-        assertFalse("Too small -ve", FloatValidator.getInstance().isValid(strTooSmallNegative, pattern));
-    }
-
-    /**
      * Test Float Range/Min/Max
      */
+    @Test
     public void testFloatRangeMinMax() {
-        final FloatValidator validator = (FloatValidator)strictValidator;
-        final Float number9  = validator.validate("9", "#");
+        final FloatValidator validator = (FloatValidator) strictValidator;
+        final Float number9 = validator.validate("9", "#");
         final Float number10 = validator.validate("10", "#");
         final Float number11 = validator.validate("11", "#");
         final Float number19 = validator.validate("19", "#");
@@ -147,20 +87,83 @@
         final Float number21 = validator.validate("21", "#");
 
         // Test isInRange()
-        assertFalse("isInRange() < min",   validator.isInRange(number9,  10, 20));
-        assertTrue("isInRange() = min",    validator.isInRange(number10, 10, 20));
-        assertTrue("isInRange() in range", validator.isInRange(number11, 10, 20));
-        assertTrue("isInRange() = max",    validator.isInRange(number20, 10, 20));
-        assertFalse("isInRange() > max",   validator.isInRange(number21, 10, 20));
+        assertFalse(validator.isInRange(number9, 10, 20), "isInRange() < min");
+        assertTrue(validator.isInRange(number10, 10, 20), "isInRange() = min");
+        assertTrue(validator.isInRange(number11, 10, 20), "isInRange() in range");
+        assertTrue(validator.isInRange(number20, 10, 20), "isInRange() = max");
+        assertFalse(validator.isInRange(number21, 10, 20), "isInRange() > max");
 
         // Test minValue()
-        assertFalse("minValue() < min",    validator.minValue(number9,  10));
-        assertTrue("minValue() = min",     validator.minValue(number10, 10));
-        assertTrue("minValue() > min",     validator.minValue(number11, 10));
+        assertFalse(validator.minValue(number9, 10), "minValue() < min");
+        assertTrue(validator.minValue(number10, 10), "minValue() = min");
+        assertTrue(validator.minValue(number11, 10), "minValue() > min");
 
         // Test minValue()
-        assertTrue("maxValue() < max",     validator.maxValue(number19, 20));
-        assertTrue("maxValue() = max",     validator.maxValue(number20, 20));
-        assertFalse("maxValue() > max",    validator.maxValue(number21, 20));
+        assertTrue(validator.maxValue(number19, 20), "maxValue() < max");
+        assertTrue(validator.maxValue(number20, 20), "maxValue() = max");
+        assertFalse(validator.maxValue(number21, 20), "maxValue() > max");
+    }
+
+    /**
+     * Test Float validation for values too small to handle. (slightly different from max/min which are the largest +ve/-ve
+     */
+    @Test
+    public void testFloatSmallestValues() {
+        final String pattern = "#.#################################################################";
+        final DecimalFormat fmt = new DecimalFormat(pattern);
+
+        // Validate Smallest +ve value
+        final Float smallestPositive = Float.valueOf(Float.MIN_VALUE);
+        final String strSmallestPositive = fmt.format(smallestPositive);
+        assertEquals(smallestPositive, FloatValidator.getInstance().validate(strSmallestPositive, pattern), "Smallest +ve");
+
+        // Validate Smallest -ve value
+        final Float smallestNegative = Float.valueOf(Float.MIN_VALUE * -1);
+        final String strSmallestNegative = fmt.format(smallestNegative);
+        assertEquals(smallestNegative, FloatValidator.getInstance().validate(strSmallestNegative, pattern), "Smallest -ve");
+
+        // Validate Too Small +ve
+        final Double tooSmallPositive = Double.valueOf((double) Float.MIN_VALUE / (double) 10);
+        final String strTooSmallPositive = fmt.format(tooSmallPositive);
+        assertFalse(FloatValidator.getInstance().isValid(strTooSmallPositive, pattern), "Too small +ve");
+
+        // Validate Too Small -ve
+        final Double tooSmallNegative = Double.valueOf(tooSmallPositive.doubleValue() * -1);
+        final String strTooSmallNegative = fmt.format(tooSmallNegative);
+        assertFalse(FloatValidator.getInstance().isValid(strTooSmallNegative, pattern), "Too small -ve");
+    }
+
+    /**
+     * Test FloatValidator validate Methods
+     */
+    @Test
+    public void testFloatValidatorMethods() {
+        final Locale locale = Locale.GERMAN;
+        final String pattern = "0,00,00";
+        final String patternVal = "1,23,45";
+        final String localeVal = "12.345";
+        final String germanPatternVal = "1.23.45";
+        final String defaultVal = "12,345";
+        final String XXXX = "XXXX";
+        final Float expected = Float.valueOf(12345);
+        assertEquals(expected, FloatValidator.getInstance().validate(defaultVal), "validate(A) default");
+        assertEquals(expected, FloatValidator.getInstance().validate(localeVal, locale), "validate(A) locale");
+        assertEquals(expected, FloatValidator.getInstance().validate(patternVal, pattern), "validate(A) pattern");
+        assertEquals(expected, FloatValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN), "validate(A) both");
+
+        assertTrue(FloatValidator.getInstance().isValid(defaultVal), "isValid(A) default");
+        assertTrue(FloatValidator.getInstance().isValid(localeVal, locale), "isValid(A) locale");
+        assertTrue(FloatValidator.getInstance().isValid(patternVal, pattern), "isValid(A) pattern");
+        assertTrue(FloatValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN), "isValid(A) both");
+
+        assertNull(FloatValidator.getInstance().validate(XXXX), "validate(B) default");
+        assertNull(FloatValidator.getInstance().validate(XXXX, locale), "validate(B) locale ");
+        assertNull(FloatValidator.getInstance().validate(XXXX, pattern), "validate(B) pattern");
+        assertNull(FloatValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN), "validate(B) both");
+
+        assertFalse(FloatValidator.getInstance().isValid(XXXX), "isValid(B) default");
+        assertFalse(FloatValidator.getInstance().isValid(XXXX, locale), "isValid(B) locale");
+        assertFalse(FloatValidator.getInstance().isValid(XXXX, pattern), "isValid(B) pattern");
+        assertFalse(FloatValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN), "isValid(B) both");
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/IBANValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/IBANValidatorTest.java
index 6f08232..e844988 100644
--- a/src/test/java/org/apache/commons/validator/routines/IBANValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/IBANValidatorTest.java
@@ -19,12 +19,12 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.Is.is;
 import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -38,11 +38,10 @@
 import org.apache.commons.csv.CSVRecord;
 import org.apache.commons.validator.routines.IBANValidator.Validator;
 import org.apache.commons.validator.routines.checkdigit.IBANCheckDigit;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
- * IBANValidator Test Case.
- * @since 1.5.0
+ * Tests {@link IBANValidator}.
  */
 public class IBANValidatorTest {
 
@@ -55,6 +54,142 @@
     private static final Pattern IBAN_PAT = Pattern
             .compile("([A-Z]{2})" + IBAN_PART + IBAN_PART + IBAN_PART + IBAN_PART + "?" + IBAN_PART + "?" + IBAN_PART + "?" + IBAN_PART + "?");
 
+    // It's not clear whether IBANs can contain lower case characters
+    // so we test for both where possible
+    // Note that the BIC near the start of the code is always upper case or digits
+    // @formatter:off
+    private static final String[] VALID_IBAN_FIXTURES = {
+            "AD1200012030200359100100",
+            "AE070331234567890123456",
+            "AL47212110090000000235698741",
+            "AT611904300234573201",
+            "AZ21NABZ00000000137010001944",
+            "BA391290079401028494",
+            "BE68539007547034",
+            "BG80BNBG96611020345678",
+            "BH67BMAG00001299123456",
+            "BI4210000100010000332045181",
+            "BR1800000000141455123924100C2",
+            "BR1800360305000010009795493C1",
+            "BR9700360305000010009795493P1",
+            "BY13NBRB3600900000002Z00AB00",
+            "CH9300762011623852957",
+            "CR05015202001026284066",
+            "CY17002001280000001200527600",
+            "CZ6508000000192000145399",
+            "CZ9455000000001011038930",
+            "DE89370400440532013000",
+            "DJ2110002010010409943020008",
+            "DK5000400440116243",
+            "DO28BAGR00000001212453611324",
+            "EE382200221020145685",
+            "EG380019000500000000263180002",
+            "ES9121000418450200051332",
+            "FI2112345600000785",
+            "FI5542345670000081",
+              // FI other
+              "AX2112345600000785", // FI other
+              "AX5542345670000081", // FI other
+            "FO6264600001631634",
+            "FR1420041010050500013M02606",
+              // FR 'other'
+              "BL6820041010050500013M02606", // FR other
+              "GF4120041010050500013M02606", // FR other
+              "GP1120041010050500013M02606", // FR other
+              "MF8420041010050500013M02606", // FR other
+              "MQ5120041010050500013M02606", // FR other
+              "NC8420041010050500013M02606", // FR other
+              "PF5720041010050500013M02606", // FR other
+              "PM3620041010050500013M02606", // FR other
+              "RE4220041010050500013M02606", // FR other
+              "TF2120041010050500013M02606", // FR other
+              "WF9120041010050500013M02606", // FR other
+              "YT3120041010050500013M02606", // FR other
+            "GB29NWBK60161331926819",
+              // GB 'other'
+//              "IM...", // GB other
+//              "JE...", // GB other
+//              "GG...", // GB other
+            "GE29NB0000000101904917",
+            "GI75NWBK000000007099453",
+            "GL8964710001000206",
+            "GR1601101250000000012300695",
+            "GT82TRAJ01020000001210029690",
+            "HR1210010051863000160",
+            "HU42117730161111101800000000",
+            "IE29AIBK93115212345678",
+            "IL620108000000099999999",
+            "IQ98NBIQ850123456789012",
+            "IS140159260076545510730339",
+            "IT60X0542811101000000123456",
+            "JO94CBJO0010000000000131000302",
+            "KW81CBKU0000000000001234560101",
+            "KZ86125KZT5004100100",
+            "LB62099900000001001901229114",
+            "LC55HEMM000100010012001200023015",
+            "LI21088100002324013AA",
+            "LT121000011101001000",
+            "LU280019400644750000",
+            "LY83002048000020100120361",
+            "LV80BANK0000435195001",
+            "LY83002048000020100120361",
+            "MC5811222000010123456789030",
+            "MD24AG000225100013104168",
+            "ME25505000012345678951",
+            "MK07250120000058984",
+            "MR1300020001010000123456753",
+            "MT84MALT011000012345MTLCAST001S",
+            "MU17BOMM0101101030300200000MUR",
+            "NL91ABNA0417164300",
+            "NO9386011117947",
+            "PK36SCBL0000001123456702",
+            "PL61109010140000071219812874",
+            "PS92PALS000000000400123456702",
+            "PT50000201231234567890154",
+            "QA58DOHB00001234567890ABCDEFG",
+            "RO49AAAA1B31007593840000",
+            "RS35260005601001611379",
+            "RU0204452560040702810412345678901",
+            "SA0380000000608010167519",
+            "SC18SSCB11010000000000001497USD",
+            "SD8811123456789012",
+            "SE4550000000058398257466",
+            "SI56191000000123438",
+            "SI56263300012039086",
+            "SK3112000000198742637541",
+            "SM86U0322509800000000270100",
+            "ST68000100010051845310112",
+            "SV62CENR00000000000000700025",
+            "SV43ACAT00000000000000123123",
+            "TL380080012345678910157",
+            "TN5910006035183598478831",
+            "TR330006100519786457841326",
+            "UA213223130000026007233566001",
+            "UA213996220000026007233566001",
+            "VA59001123000012345678",
+            "VG96VPVG0000012345678901",
+            "XK051212012345678906",
+    };
+    // @formatter:on
+
+    // @formatter:off
+    private static final String[] INVALID_IBAN_FIXTURES = {
+            "",                        // empty
+            "   ",                     // empty
+            "A",                       // too short
+            "AB",                      // too short
+            "FR1420041010050500013m02606", // lowercase version
+            "MT84MALT011000012345mtlcast001s", // lowercase version
+            "LI21088100002324013aa", // lowercase version
+            "QA58DOHB00001234567890abcdefg", // lowercase version
+            "RO49AAAA1b31007593840000", // lowercase version
+            "LC62HEMM000100010012001200023015", // wrong in SWIFT
+            "BY00NBRB3600000000000Z00AB00", // Wrong in SWIFT v73
+            "ST68000200010192194210112", // ditto
+            "SV62CENR0000000000000700025", // ditto
+    };
+    // @formatter:on
+
     private static int checkIBAN(final File file, final IBANValidator val) throws Exception {
         // The IBAN Registry (TXT) file is a TAB-separated file
         // Rows are the entry types, columns are the countries
@@ -177,176 +312,36 @@
 
     private static void printEntry(final String ccode, final String length, final String ib, final String country) {
         final String fmt = String.format("\"%s\"", ib);
-        System.out.printf("            new Validator(\"%s\", %s, %-40s), // %s\n",
-                ccode,
-                length,
-                fmt,
-                country);
+        System.out.printf("            new Validator(\"%s\", %s, %-40s), // %s\n", ccode, length, fmt, country);
     }
 
-    // It's not clear whether IBANs can contain lower case characters
-    // so we test for both where possible
-    // Note that the BIC near the start of the code is always upper case or digits
-    // @formatter:off
-    private static final String[] VALID_IBAN_FIXTURES = {
-            "AD1200012030200359100100",
-            "AE070331234567890123456",
-            "AL47212110090000000235698741",
-            "AT611904300234573201",
-            "AZ21NABZ00000000137010001944",
-            "BA391290079401028494",
-            "BE68539007547034",
-            "BG80BNBG96611020345678",
-            "BH67BMAG00001299123456",
-            "BI4210000100010000332045181",
-            "BR1800000000141455123924100C2",
-            "BR1800360305000010009795493C1",
-            "BR9700360305000010009795493P1",
-            "BY13NBRB3600900000002Z00AB00",
-            "CH9300762011623852957",
-            "CR05015202001026284066",
-            "CY17002001280000001200527600",
-            "CZ6508000000192000145399",
-            "CZ9455000000001011038930",
-            "DE89370400440532013000",
-            "DJ2110002010010409943020008",
-            "DK5000400440116243",
-            "DO28BAGR00000001212453611324",
-            "EE382200221020145685",
-            "EG380019000500000000263180002",
-            "ES9121000418450200051332",
-            "FI2112345600000785",
-            "FI5542345670000081",
-              // FI other
-              "AX2112345600000785", // FI other
-              "AX5542345670000081", // FI other
-            "FO6264600001631634",
-            "FR1420041010050500013M02606",
-              // FR 'other'             
-              "BL6820041010050500013M02606", // FR other
-              "GF4120041010050500013M02606", // FR other
-              "GP1120041010050500013M02606", // FR other
-              "MF8420041010050500013M02606", // FR other
-              "MQ5120041010050500013M02606", // FR other
-              "NC8420041010050500013M02606", // FR other
-              "PF5720041010050500013M02606", // FR other
-              "PM3620041010050500013M02606", // FR other
-              "RE4220041010050500013M02606", // FR other
-              "TF2120041010050500013M02606", // FR other
-              "WF9120041010050500013M02606", // FR other
-              "YT3120041010050500013M02606", // FR other
-            "GB29NWBK60161331926819",
-              // GB 'other'            
-//              "IM...", // GB other
-//              "JE...", // GB other
-//              "GG...", // GB other
-            "GE29NB0000000101904917",
-            "GI75NWBK000000007099453",
-            "GL8964710001000206",
-            "GR1601101250000000012300695",
-            "GT82TRAJ01020000001210029690",
-            "HR1210010051863000160",
-            "HU42117730161111101800000000",
-            "IE29AIBK93115212345678",
-            "IL620108000000099999999",
-            "IQ98NBIQ850123456789012",
-            "IS140159260076545510730339",
-            "IT60X0542811101000000123456",
-            "JO94CBJO0010000000000131000302",
-            "KW81CBKU0000000000001234560101",
-            "KZ86125KZT5004100100",
-            "LB62099900000001001901229114",
-            "LC55HEMM000100010012001200023015",
-            "LI21088100002324013AA",
-            "LT121000011101001000",
-            "LU280019400644750000",
-            "LY83002048000020100120361",
-            "LV80BANK0000435195001",
-            "LY83002048000020100120361",
-            "MC5811222000010123456789030",
-            "MD24AG000225100013104168",
-            "ME25505000012345678951",
-            "MK07250120000058984",
-            "MR1300020001010000123456753",
-            "MT84MALT011000012345MTLCAST001S",
-            "MU17BOMM0101101030300200000MUR",
-            "NL91ABNA0417164300",
-            "NO9386011117947",
-            "PK36SCBL0000001123456702",
-            "PL61109010140000071219812874",
-            "PS92PALS000000000400123456702",
-            "PT50000201231234567890154",
-            "QA58DOHB00001234567890ABCDEFG",
-            "RO49AAAA1B31007593840000",
-            "RS35260005601001611379",
-            "RU0204452560040702810412345678901",
-            "SA0380000000608010167519",
-            "SC18SSCB11010000000000001497USD",
-            "SD8811123456789012",
-            "SE4550000000058398257466",
-            "SI56191000000123438",
-            "SI56263300012039086",
-            "SK3112000000198742637541",
-            "SM86U0322509800000000270100",
-            "ST68000100010051845310112",
-            "SV62CENR00000000000000700025",
-            "SV43ACAT00000000000000123123",
-            "TL380080012345678910157",
-            "TN5910006035183598478831",
-            "TR330006100519786457841326",
-            "UA213223130000026007233566001",
-            "UA213996220000026007233566001",
-            "VA59001123000012345678",
-            "VG96VPVG0000012345678901",
-            "XK051212012345678906",
-    };
-    // @formatter:on
-
-    // @formatter:off
-    private static final String[] INVALID_IBAN_FIXTURES = {
-            "",                        // empty
-            "   ",                     // empty
-            "A",                       // too short
-            "AB",                      // too short
-            "FR1420041010050500013m02606", // lowercase version
-            "MT84MALT011000012345mtlcast001s", // lowercase version
-            "LI21088100002324013aa", // lowercase version
-            "QA58DOHB00001234567890abcdefg", // lowercase version
-            "RO49AAAA1b31007593840000", // lowercase version
-            "LC62HEMM000100010012001200023015", // wrong in SWIFT
-            "BY00NBRB3600000000000Z00AB00", // Wrong in SWIFT v73
-            "ST68000200010192194210112", // ditto
-            "SV62CENR0000000000000700025", // ditto
-    };
-    // @formatter:on
-
     @Test
     public void testGetRegexValidatortPatterns() {
-        assertNotNull("GB", VALIDATOR.getValidator("GB").getRegexValidator().getPatterns());
+        assertNotNull(VALIDATOR.getValidator("GB").getRegexValidator().getPatterns(), "GB");
     }
 
     @Test
     public void testGetValidator() {
-        assertNotNull("GB", VALIDATOR.getValidator("GB"));
-        assertNull("gb", VALIDATOR.getValidator("gb"));
+        assertNotNull(VALIDATOR.getValidator("GB"), "GB");
+        assertNull(VALIDATOR.getValidator("gb"), "gb");
     }
 
     @Test
     public void testHasValidator() {
-        assertTrue("GB", VALIDATOR.hasValidator("GB"));
-        assertFalse("gb", VALIDATOR.hasValidator("gb"));
+        assertTrue(VALIDATOR.hasValidator("GB"), "GB");
+        assertFalse(VALIDATOR.hasValidator("gb"), "gb");
     }
 
     @Test
     public void testInValid() {
         for (final String f : INVALID_IBAN_FIXTURES) {
-            assertFalse(f, VALIDATOR.isValid(f));
+            assertFalse(VALIDATOR.isValid(f), f);
         }
     }
 
     @Test
     public void testNull() {
-        assertFalse("isValid(null)", VALIDATOR.isValid(null));
+        assertFalse(VALIDATOR.isValid(null), "isValid(null)");
     }
 
     @Test
@@ -371,8 +366,8 @@
     @Test
     public void testSetValidatorLen_1() {
         final IBANValidator validator = new IBANValidator();
-        assertNotNull("should be present", validator.setValidator("GB", -1, ""));
-        assertNull("no longer present", validator.setValidator("GB", -1, ""));
+        assertNotNull(validator.setValidator("GB", -1, ""), "should be present");
+        assertNull(validator.setValidator("GB", -1, ""), "no longer present");
     }
 
     @Test
@@ -404,9 +399,9 @@
     @Test
     public void testValid() {
         for (final String f : VALID_IBAN_FIXTURES) {
-            assertTrue("Checksum fail: " + f, IBANCheckDigit.IBAN_CHECK_DIGIT.isValid(f));
-            assertTrue("Missing validator: " + f, VALIDATOR.hasValidator(f));
-            assertTrue(f, VALIDATOR.isValid(f));
+            assertTrue(IBANCheckDigit.IBAN_CHECK_DIGIT.isValid(f), "Checksum fail: " + f);
+            assertTrue(VALIDATOR.hasValidator(f), "Missing validator: " + f);
+            assertTrue(VALIDATOR.isValid(f), f);
         }
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/ISBNValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/ISBNValidatorTest.java
index aaefc05..0a66225 100644
--- a/src/test/java/org/apache/commons/validator/routines/ISBNValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/ISBNValidatorTest.java
@@ -16,279 +16,75 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.util.regex.Pattern;
 
-import junit.framework.TestCase;
+import org.junit.jupiter.api.Test;
 
 /**
- * ISBNValidator Test Case.
+ * Tests {@link ISBNValidator}.
  */
-public class ISBNValidatorTest extends TestCase {
+public class ISBNValidatorTest {
 
-    private final String[] validISBN10Format = {
-            "1234567890",
-            "123456789X",
-            "12345-1234567-123456-X",
-            "12345 1234567 123456 X",
-            "1-2-3-4",
-            "1 2 3 4",
-            };
+    private final String[] validISBN10Format = { "1234567890", "123456789X", "12345-1234567-123456-X", "12345 1234567 123456 X", "1-2-3-4", "1 2 3 4", };
 
-    private final String[] invalidISBN10Format = {
-            "",                        // empty
-            "   ",                     // empty
-            "1",                       // too short
-            "123456789",               // too short
-            "12345678901",             // too long
-            "12345678X0",              // X not at end
+    private final String[] invalidISBN10Format = { "", // empty
+            "   ", // empty
+            "1", // too short
+            "123456789", // too short
+            "12345678901", // too long
+            "12345678X0", // X not at end
             "123456-1234567-123456-X", // Group too long
             "12345-12345678-123456-X", // Publisher too long
             "12345-1234567-1234567-X", // Title too long
             "12345-1234567-123456-X2", // Check Digit too long
-            "--1 930110 99 5",         // format
-            "1 930110 99 5--",         // format
-            "1 930110-99 5-",          // format
-            "1.2.3.4",                 // Invalid Separator
-            "1=2=3=4",                 // Invalid Separator
-            "1_2_3_4",                 // Invalid Separator
-            "123456789Y",              // Other character at the end
-            "dsasdsadsa",              // invalid characters
-            "I love sparrows!",        // invalid characters
-            "068-556-98-45"            // format
-            };
+            "--1 930110 99 5", // format
+            "1 930110 99 5--", // format
+            "1 930110-99 5-", // format
+            "1.2.3.4", // Invalid Separator
+            "1=2=3=4", // Invalid Separator
+            "1_2_3_4", // Invalid Separator
+            "123456789Y", // Other character at the end
+            "dsasdsadsa", // invalid characters
+            "I love sparrows!", // invalid characters
+            "068-556-98-45" // format
+    };
 
-    private final String[] validISBN13Format = {
-            "9781234567890",
-            "9791234567890",
-            "978-12345-1234567-123456-1",
-            "979-12345-1234567-123456-1",
-            "978 12345 1234567 123456 1",
-            "979 12345 1234567 123456 1",
-            "978-1-2-3-4",
-            "979-1-2-3-4",
-            "978 1 2 3 4",
-            "979 1 2 3 4",
-            };
+    private final String[] validISBN13Format = { "9781234567890", "9791234567890", "978-12345-1234567-123456-1", "979-12345-1234567-123456-1",
+            "978 12345 1234567 123456 1", "979 12345 1234567 123456 1", "978-1-2-3-4", "979-1-2-3-4", "978 1 2 3 4", "979 1 2 3 4", };
 
-    private final String[] invalidISBN13Format = {
-            "",                            // empty
-            "   ",                         // empty
-            "1",                           // too short
-            "978123456789",                // too short
-            "97812345678901",              // too long
+    private final String[] invalidISBN13Format = { "", // empty
+            "   ", // empty
+            "1", // too short
+            "978123456789", // too short
+            "97812345678901", // too long
             "978-123456-1234567-123456-1", // Group too long
             "978-12345-12345678-123456-1", // Publisher too long
             "978-12345-1234567-1234567-1", // Title too long
             "978-12345-1234567-123456-12", // Check Digit too long
-            "--978 1 930110 99 1",         // format
-            "978 1 930110 99 1--",         // format
-            "978 1 930110-99 1-",          // format
-            "123-4-567890-12-8",           // format
-            "978.1.2.3.4",                 // Invalid Separator
-            "978=1=2=3=4",                 // Invalid Separator
-            "978_1_2_3_4",                 // Invalid Separator
-            "978123456789X",               // invalid character
-            "978-0-201-63385-X",           // invalid character
-            "dsasdsadsadsa",               // invalid characters
-            "I love sparrows!",            // invalid characters
-            "979-1-234-567-89-6"           // format
-            };
-
-    /**
-     * Create a test case with the specified name.
-     * @param name The name of the test
-     */
-    public ISBNValidatorTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Test Valid ISBN-10 formats.
-     */
-    public void testValidISBN10Format() {
-        final Pattern pattern = Pattern.compile(ISBNValidator.ISBN10_REGEX);
-        for (int i = 0; i < validISBN10Format.length; i++) {
-            assertTrue("Pattern[" + i + "]=" + validISBN10Format[i], pattern.matcher(validISBN10Format[i]).matches());
-        }
-    }
-
-    /**
-     * Test Invalid ISBN-10 formats.
-     */
-    public void testInvalidISBN10Format() {
-        final ISBNValidator validator = ISBNValidator.getInstance();
-        final Pattern pattern = Pattern.compile(ISBNValidator.ISBN10_REGEX);
-        for (int i = 0; i < invalidISBN10Format.length; i++) {
-            assertFalse("Pattern[" + i + "]=" + invalidISBN10Format[i],       pattern.matcher(invalidISBN10Format[i]).matches());
-            assertFalse("isValidISBN10[" + i + "]=" + invalidISBN10Format[i], validator.isValidISBN10(invalidISBN10Format[i]));
-            assertNull("validateISBN10[" + i + "]=" + invalidISBN10Format[i], validator.validateISBN10(invalidISBN10Format[i]));
-        }
-    }
-
-    /**
-     * Test Valid ISBN-13 formats.
-     */
-    public void testValidISBN13Format() {
-        final Pattern pattern = Pattern.compile(ISBNValidator.ISBN13_REGEX);
-        for (int i = 0; i < validISBN13Format.length; i++) {
-            assertTrue("Pattern[" + i + "]=" + validISBN13Format[i], pattern.matcher(validISBN13Format[i]).matches());
-        }
-    }
-
-    /**
-     * Test Invalid ISBN-13 formats.
-     */
-    public void testInvalidISBN13Format() {
-        final Pattern pattern = Pattern.compile(ISBNValidator.ISBN13_REGEX);
-        final ISBNValidator validator = ISBNValidator.getInstance();
-        for (int i = 0; i < invalidISBN13Format.length; i++) {
-            assertFalse("Pattern[" + i + "]=" + invalidISBN13Format[i],       pattern.matcher(invalidISBN13Format[i]).matches());
-            assertFalse("isValidISBN13[" + i + "]=" + invalidISBN13Format[i], validator.isValidISBN13(invalidISBN13Format[i]));
-            assertNull("validateISBN13[" + i + "]=" + invalidISBN13Format[i], validator.validateISBN13(invalidISBN13Format[i]));
-        }
-    }
-
-    /**
-     * Test isValid() ISBN-10 codes
-     */
-    public void testIsValidISBN10() {
-        final ISBNValidator validator = ISBNValidator.getInstance();
-        assertTrue("isValidISBN10-1", validator.isValidISBN10("1930110995"));
-        assertTrue("isValidISBN10-2", validator.isValidISBN10("1-930110-99-5"));
-        assertTrue("isValidISBN10-3", validator.isValidISBN10("1 930110 99 5"));
-        assertTrue("isValidISBN10-4", validator.isValidISBN10("020163385X"));
-        assertTrue("isValidISBN10-5", validator.isValidISBN10("0-201-63385-X"));
-        assertTrue("isValidISBN10-6", validator.isValidISBN10("0 201 63385 X"));
-
-        assertTrue("isValid-1", validator.isValid("1930110995"));
-        assertTrue("isValid-2", validator.isValid("1-930110-99-5"));
-        assertTrue("isValid-3", validator.isValid("1 930110 99 5"));
-        assertTrue("isValid-4", validator.isValid("020163385X"));
-        assertTrue("isValid-5", validator.isValid("0-201-63385-X"));
-        assertTrue("isValid-6", validator.isValid("0 201 63385 X"));
-    }
-
-    /**
-     * Test isValid() ISBN-13 codes
-     */
-    public void testIsValidISBN13() {
-        final ISBNValidator validator = ISBNValidator.getInstance();
-        assertTrue("isValidISBN13-1", validator.isValidISBN13("9781930110991"));
-        assertTrue("isValidISBN13-2", validator.isValidISBN13("978-1-930110-99-1"));
-        assertTrue("isValidISBN13-3", validator.isValidISBN13("978 1 930110 99 1"));
-        assertTrue("isValidISBN13-4", validator.isValidISBN13("9780201633856"));
-        assertTrue("isValidISBN13-5", validator.isValidISBN13("978-0-201-63385-6"));
-        assertTrue("isValidISBN13-6", validator.isValidISBN13("978 0 201 63385 6"));
-
-        assertTrue("isValid-1", validator.isValid("9781930110991"));
-        assertTrue("isValid-2", validator.isValid("978-1-930110-99-1"));
-        assertTrue("isValid-3", validator.isValid("978 1 930110 99 1"));
-        assertTrue("isValid-4", validator.isValid("9780201633856"));
-        assertTrue("isValid-5", validator.isValid("978-0-201-63385-6"));
-        assertTrue("isValid-6", validator.isValid("978 0 201 63385 6"));
-    }
-
-    /**
-     * Test validate() ISBN-10 codes (don't convert)
-     */
-    public void testValidateISBN10() {
-        final ISBNValidator validator = ISBNValidator.getInstance(false);
-        assertEquals("validateISBN10-1", "1930110995", validator.validateISBN10("1930110995"));
-        assertEquals("validateISBN10-2", "1930110995", validator.validateISBN10("1-930110-99-5"));
-        assertEquals("validateISBN10-3", "1930110995", validator.validateISBN10("1 930110 99 5"));
-        assertEquals("validateISBN10-4", "020163385X", validator.validateISBN10("020163385X"));
-        assertEquals("validateISBN10-5", "020163385X", validator.validateISBN10("0-201-63385-X"));
-        assertEquals("validateISBN10-6", "020163385X", validator.validateISBN10("0 201 63385 X"));
-
-        assertEquals("validate-1", "1930110995", validator.validate("1930110995"));
-        assertEquals("validate-2", "1930110995", validator.validate("1-930110-99-5"));
-        assertEquals("validate-3", "1930110995", validator.validate("1 930110 99 5"));
-        assertEquals("validate-4", "020163385X", validator.validate("020163385X"));
-        assertEquals("validate-5", "020163385X", validator.validate("0-201-63385-X"));
-        assertEquals("validate-6", "020163385X", validator.validate("0 201 63385 X"));
-    }
-
-    /**
-     * Test validate() ISBN-10 codes (convert)
-     */
-    public void testValidateISBN10Convert() {
-        final ISBNValidator validator = ISBNValidator.getInstance();
-        assertEquals("validate-1", "9781930110991", validator.validate("1930110995"));
-        assertEquals("validate-2", "9781930110991", validator.validate("1-930110-99-5"));
-        assertEquals("validate-3", "9781930110991", validator.validate("1 930110 99 5"));
-        assertEquals("validate-4", "9780201633856", validator.validate("020163385X"));
-        assertEquals("validate-5", "9780201633856", validator.validate("0-201-63385-X"));
-        assertEquals("validate-6", "9780201633856", validator.validate("0 201 63385 X"));
-    }
-
-    /**
-     * Test validate() ISBN-13 codes
-     */
-    public void testValidateISBN13() {
-        final ISBNValidator validator = ISBNValidator.getInstance();
-        assertEquals("validateISBN13-1", "9781930110991", validator.validateISBN13("9781930110991"));
-        assertEquals("validateISBN13-2", "9781930110991", validator.validateISBN13("978-1-930110-99-1"));
-        assertEquals("validateISBN13-3", "9781930110991", validator.validateISBN13("978 1 930110 99 1"));
-        assertEquals("validateISBN13-4", "9780201633856", validator.validateISBN13("9780201633856"));
-        assertEquals("validateISBN13-5", "9780201633856", validator.validateISBN13("978-0-201-63385-6"));
-        assertEquals("validateISBN13-6", "9780201633856", validator.validateISBN13("978 0 201 63385 6"));
-
-        assertEquals("validate-1", "9781930110991", validator.validate("9781930110991"));
-        assertEquals("validate-2", "9781930110991", validator.validate("978-1-930110-99-1"));
-        assertEquals("validate-3", "9781930110991", validator.validate("978 1 930110 99 1"));
-        assertEquals("validate-4", "9780201633856", validator.validate("9780201633856"));
-        assertEquals("validate-5", "9780201633856", validator.validate("978-0-201-63385-6"));
-        assertEquals("validate-6", "9780201633856", validator.validate("978 0 201 63385 6"));
-    }
-
-    /**
-     * Test null values
-     */
-    public void testNull() {
-        final ISBNValidator validator = ISBNValidator.getInstance();
-        assertFalse("isValid",        validator.isValid(null));
-        assertFalse("isValidISBN10",  validator.isValidISBN10(null));
-        assertFalse("isValidISBN13",  validator.isValidISBN13(null));
-        assertNull("validate",        validator.validate(null));
-        assertNull("validateISBN10",  validator.validateISBN10(null));
-        assertNull("validateISBN13",  validator.validateISBN13(null));
-        assertNull("convertToISBN13", validator.convertToISBN13(null));
-    }
-
-    /**
-     * Test Invalid ISBN-10 codes
-     */
-    public void testInvalid() {
-        final ISBNValidator validator = ISBNValidator.getInstance();
-        String baseCode = "193011099";
-        assertFalse("ISBN10-0", validator.isValid(baseCode + "0"));
-        assertFalse("ISBN10-1", validator.isValid(baseCode + "1"));
-        assertFalse("ISBN10-2", validator.isValid(baseCode + "2"));
-        assertFalse("ISBN10-3", validator.isValid(baseCode + "3"));
-        assertFalse("ISBN10-4", validator.isValid(baseCode + "4"));
-        assertTrue("ISBN10-5",  validator.isValid(baseCode + "5")); // valid check digit
-        assertFalse("ISBN10-6", validator.isValid(baseCode + "6"));
-        assertFalse("ISBN10-7", validator.isValid(baseCode + "7"));
-        assertFalse("ISBN10-8", validator.isValid(baseCode + "8"));
-        assertFalse("ISBN10-9", validator.isValid(baseCode + "9"));
-        assertFalse("ISBN10-X", validator.isValid(baseCode + "X"));
-
-        baseCode = "978193011099";
-        assertFalse("ISBN13-0", validator.isValid(baseCode + "0"));
-        assertTrue("ISBN13-1",  validator.isValid(baseCode + "1")); // valid check digit
-        assertFalse("ISBN13-2", validator.isValid(baseCode + "2"));
-        assertFalse("ISBN13-3", validator.isValid(baseCode + "3"));
-        assertFalse("ISBN13-4", validator.isValid(baseCode + "4"));
-        assertFalse("ISBN13-5", validator.isValid(baseCode + "5"));
-        assertFalse("ISBN13-6", validator.isValid(baseCode + "6"));
-        assertFalse("ISBN13-7", validator.isValid(baseCode + "7"));
-        assertFalse("ISBN13-8", validator.isValid(baseCode + "8"));
-        assertFalse("ISBN13-9", validator.isValid(baseCode + "9"));
-    }
+            "--978 1 930110 99 1", // format
+            "978 1 930110 99 1--", // format
+            "978 1 930110-99 1-", // format
+            "123-4-567890-12-8", // format
+            "978.1.2.3.4", // Invalid Separator
+            "978=1=2=3=4", // Invalid Separator
+            "978_1_2_3_4", // Invalid Separator
+            "978123456789X", // invalid character
+            "978-0-201-63385-X", // invalid character
+            "dsasdsadsadsa", // invalid characters
+            "I love sparrows!", // invalid characters
+            "979-1-234-567-89-6" // format
+    };
 
     /**
      * Test method for {@link org.apache.commons.validator.routines.ISBNValidator#convertToISBN13(java.lang.String)}.
      */
+    @Test
     public void testConversionErrors() {
         final ISBNValidator validator = ISBNValidator.getInstance();
         String input = null;
@@ -322,4 +118,199 @@
         }
     }
 
+    /**
+     * Test Invalid ISBN-10 codes
+     */
+    @Test
+    public void testInvalid() {
+        final ISBNValidator validator = ISBNValidator.getInstance();
+        String baseCode = "193011099";
+        assertFalse(validator.isValid(baseCode + "0"), "ISBN10-0");
+        assertFalse(validator.isValid(baseCode + "1"), "ISBN10-1");
+        assertFalse(validator.isValid(baseCode + "2"), "ISBN10-2");
+        assertFalse(validator.isValid(baseCode + "3"), "ISBN10-3");
+        assertFalse(validator.isValid(baseCode + "4"), "ISBN10-4");
+        assertTrue(validator.isValid(baseCode + "5"), "ISBN10-5"); // valid check digit
+        assertFalse(validator.isValid(baseCode + "6"), "ISBN10-6");
+        assertFalse(validator.isValid(baseCode + "7"), "ISBN10-7");
+        assertFalse(validator.isValid(baseCode + "8"), "ISBN10-8");
+        assertFalse(validator.isValid(baseCode + "9"), "ISBN10-9");
+        assertFalse(validator.isValid(baseCode + "X"), "ISBN10-X");
+
+        baseCode = "978193011099";
+        assertFalse(validator.isValid(baseCode + "0"), "ISBN13-0");
+        assertTrue(validator.isValid(baseCode + "1"), "ISBN13-1"); // valid check digit
+        assertFalse(validator.isValid(baseCode + "2"), "ISBN13-2");
+        assertFalse(validator.isValid(baseCode + "3"), "ISBN13-3");
+        assertFalse(validator.isValid(baseCode + "4"), "ISBN13-4");
+        assertFalse(validator.isValid(baseCode + "5"), "ISBN13-5");
+        assertFalse(validator.isValid(baseCode + "6"), "ISBN13-6");
+        assertFalse(validator.isValid(baseCode + "7"), "ISBN13-7");
+        assertFalse(validator.isValid(baseCode + "8"), "ISBN13-8");
+        assertFalse(validator.isValid(baseCode + "9"), "ISBN13-9");
+    }
+
+    /**
+     * Test Invalid ISBN-10 formats.
+     */
+    @Test
+    public void testInvalidISBN10Format() {
+        final ISBNValidator validator = ISBNValidator.getInstance();
+        final Pattern pattern = Pattern.compile(ISBNValidator.ISBN10_REGEX);
+        for (int i = 0; i < invalidISBN10Format.length; i++) {
+            assertFalse(pattern.matcher(invalidISBN10Format[i]).matches(), "Pattern[" + i + "]=" + invalidISBN10Format[i]);
+            assertFalse(validator.isValidISBN10(invalidISBN10Format[i]), "isValidISBN10[" + i + "]=" + invalidISBN10Format[i]);
+            assertNull(validator.validateISBN10(invalidISBN10Format[i]), "validateISBN10[" + i + "]=" + invalidISBN10Format[i]);
+        }
+    }
+
+    /**
+     * Test Invalid ISBN-13 formats.
+     */
+    @Test
+    public void testInvalidISBN13Format() {
+        final Pattern pattern = Pattern.compile(ISBNValidator.ISBN13_REGEX);
+        final ISBNValidator validator = ISBNValidator.getInstance();
+        for (int i = 0; i < invalidISBN13Format.length; i++) {
+            assertFalse(pattern.matcher(invalidISBN13Format[i]).matches(), "Pattern[" + i + "]=" + invalidISBN13Format[i]);
+            assertFalse(validator.isValidISBN13(invalidISBN13Format[i]), "isValidISBN13[" + i + "]=" + invalidISBN13Format[i]);
+            assertNull(validator.validateISBN13(invalidISBN13Format[i]), "validateISBN13[" + i + "]=" + invalidISBN13Format[i]);
+        }
+    }
+
+    /**
+     * Test isValid() ISBN-10 codes
+     */
+    @Test
+    public void testIsValidISBN10() {
+        final ISBNValidator validator = ISBNValidator.getInstance();
+        assertTrue(validator.isValidISBN10("1930110995"), "isValidISBN10-1");
+        assertTrue(validator.isValidISBN10("1-930110-99-5"), "isValidISBN10-2");
+        assertTrue(validator.isValidISBN10("1 930110 99 5"), "isValidISBN10-3");
+        assertTrue(validator.isValidISBN10("020163385X"), "isValidISBN10-4");
+        assertTrue(validator.isValidISBN10("0-201-63385-X"), "isValidISBN10-5");
+        assertTrue(validator.isValidISBN10("0 201 63385 X"), "isValidISBN10-6");
+
+        assertTrue(validator.isValid("1930110995"), "isValid-1");
+        assertTrue(validator.isValid("1-930110-99-5"), "isValid-2");
+        assertTrue(validator.isValid("1 930110 99 5"), "isValid-3");
+        assertTrue(validator.isValid("020163385X"), "isValid-4");
+        assertTrue(validator.isValid("0-201-63385-X"), "isValid-5");
+        assertTrue(validator.isValid("0 201 63385 X"), "isValid-6");
+    }
+
+    /**
+     * Test isValid() ISBN-13 codes
+     */
+    @Test
+    public void testIsValidISBN13() {
+        final ISBNValidator validator = ISBNValidator.getInstance();
+        assertTrue(validator.isValidISBN13("9781930110991"), "isValidISBN13-1");
+        assertTrue(validator.isValidISBN13("978-1-930110-99-1"), "isValidISBN13-2");
+        assertTrue(validator.isValidISBN13("978 1 930110 99 1"), "isValidISBN13-3");
+        assertTrue(validator.isValidISBN13("9780201633856"), "isValidISBN13-4");
+        assertTrue(validator.isValidISBN13("978-0-201-63385-6"), "isValidISBN13-5");
+        assertTrue(validator.isValidISBN13("978 0 201 63385 6"), "isValidISBN13-6");
+
+        assertTrue(validator.isValid("9781930110991"), "isValid-1");
+        assertTrue(validator.isValid("978-1-930110-99-1"), "isValid-2");
+        assertTrue(validator.isValid("978 1 930110 99 1"), "isValid-3");
+        assertTrue(validator.isValid("9780201633856"), "isValid-4");
+        assertTrue(validator.isValid("978-0-201-63385-6"), "isValid-5");
+        assertTrue(validator.isValid("978 0 201 63385 6"), "isValid-6");
+    }
+
+    /**
+     * Test null values
+     */
+    @Test
+    public void testNull() {
+        final ISBNValidator validator = ISBNValidator.getInstance();
+        assertFalse(validator.isValid(null), "isValid");
+        assertFalse(validator.isValidISBN10(null), "isValidISBN10");
+        assertFalse(validator.isValidISBN13(null), "isValidISBN13");
+        assertNull(validator.validate(null), "validate");
+        assertNull(validator.validateISBN10(null), "validateISBN10");
+        assertNull(validator.validateISBN13(null), "validateISBN13");
+        assertNull(validator.convertToISBN13(null), "convertToISBN13");
+    }
+
+    /**
+     * Test validate() ISBN-10 codes (don't convert)
+     */
+    @Test
+    public void testValidateISBN10() {
+        final ISBNValidator validator = ISBNValidator.getInstance(false);
+        assertEquals(validator.validateISBN10("1930110995"), "1930110995", "validateISBN10-1");
+        assertEquals(validator.validateISBN10("1-930110-99-5"), "1930110995", "validateISBN10-2");
+        assertEquals(validator.validateISBN10("1 930110 99 5"), "1930110995", "validateISBN10-3");
+        assertEquals(validator.validateISBN10("020163385X"), "020163385X", "validateISBN10-4");
+        assertEquals(validator.validateISBN10("0-201-63385-X"), "020163385X", "validateISBN10-5");
+        assertEquals(validator.validateISBN10("0 201 63385 X"), "020163385X", "validateISBN10-6");
+
+        assertEquals(validator.validate("1930110995"), "1930110995", "validate-1");
+        assertEquals(validator.validate("1-930110-99-5"), "1930110995", "validate-2");
+        assertEquals(validator.validate("1 930110 99 5"), "1930110995", "validate-3");
+        assertEquals(validator.validate("020163385X"), "020163385X", "validate-4");
+        assertEquals(validator.validate("0-201-63385-X"), "020163385X", "validate-5");
+        assertEquals(validator.validate("0 201 63385 X"), "020163385X", "validate-6");
+    }
+
+    /**
+     * Test validate() ISBN-10 codes (convert)
+     */
+    @Test
+    public void testValidateISBN10Convert() {
+        final ISBNValidator validator = ISBNValidator.getInstance();
+        assertEquals(validator.validate("1930110995"), "9781930110991", "validate-1");
+        assertEquals(validator.validate("1-930110-99-5"), "9781930110991", "validate-2");
+        assertEquals(validator.validate("1 930110 99 5"), "9781930110991", "validate-3");
+        assertEquals(validator.validate("020163385X"), "9780201633856", "validate-4");
+        assertEquals(validator.validate("0-201-63385-X"), "9780201633856", "validate-5");
+        assertEquals(validator.validate("0 201 63385 X"), "9780201633856", "validate-6");
+    }
+
+    /**
+     * Test validate() ISBN-13 codes
+     */
+    @Test
+    public void testValidateISBN13() {
+        final ISBNValidator validator = ISBNValidator.getInstance();
+        assertEquals(validator.validateISBN13("9781930110991"), "9781930110991", "validateISBN13-1");
+        assertEquals(validator.validateISBN13("978-1-930110-99-1"), "9781930110991", "validateISBN13-2");
+        assertEquals(validator.validateISBN13("978 1 930110 99 1"), "9781930110991", "validateISBN13-3");
+        assertEquals(validator.validateISBN13("9780201633856"), "9780201633856", "validateISBN13-4");
+        assertEquals(validator.validateISBN13("978-0-201-63385-6"), "9780201633856", "validateISBN13-5");
+        assertEquals(validator.validateISBN13("978 0 201 63385 6"), "9780201633856", "validateISBN13-6");
+
+        assertEquals(validator.validate("9781930110991"), "9781930110991", "validate-1");
+        assertEquals(validator.validate("978-1-930110-99-1"), "9781930110991", "validate-2");
+        assertEquals(validator.validate("978 1 930110 99 1"), "9781930110991", "validate-3");
+        assertEquals(validator.validate("9780201633856"), "9780201633856", "validate-4");
+        assertEquals(validator.validate("978-0-201-63385-6"), "9780201633856", "validate-5");
+        assertEquals(validator.validate("978 0 201 63385 6"), "9780201633856", "validate-6");
+    }
+
+    /**
+     * Test Valid ISBN-10 formats.
+     */
+    @Test
+    public void testValidISBN10Format() {
+        final Pattern pattern = Pattern.compile(ISBNValidator.ISBN10_REGEX);
+        for (int i = 0; i < validISBN10Format.length; i++) {
+            assertTrue(pattern.matcher(validISBN10Format[i]).matches(), "Pattern[" + i + "]=" + validISBN10Format[i]);
+        }
+    }
+
+    /**
+     * Test Valid ISBN-13 formats.
+     */
+    @Test
+    public void testValidISBN13Format() {
+        final Pattern pattern = Pattern.compile(ISBNValidator.ISBN13_REGEX);
+        for (int i = 0; i < validISBN13Format.length; i++) {
+            assertTrue(pattern.matcher(validISBN13Format[i]).matches(), "Pattern[" + i + "]=" + validISBN13Format[i]);
+        }
+    }
+
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/ISINValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/ISINValidatorTest.java
index 315ba65..cd418da 100644
--- a/src/test/java/org/apache/commons/validator/routines/ISINValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/ISINValidatorTest.java
@@ -16,19 +16,21 @@
  */
 package org.apache.commons.validator.routines;
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
 
 /**
- * ISINValidator Test Case.
- *
- * @since 1.7
+ * Tests {@link ISINValidator}.
  */
-public class ISINValidatorTest extends TestCase {
+public class ISINValidatorTest {
 
     private static final ISINValidator VALIDATOR_TRUE = ISINValidator.getInstance(true);
 
     private static final ISINValidator VALIDATOR_FALSE = ISINValidator.getInstance(false);
 
+    // @formatter:off
     private final String[] validFormat = {
             "US0378331005",
             "BMG8571G1096",
@@ -43,7 +45,6 @@
             "US032511BN64",
             "INE112A01023",
             "EZ0000000003", // Invented; for use in ISINValidator
-            "XS0000000009",
             "EU000A0VUCF1",
             "XA2053913989",
             "XB0000000008",
@@ -53,12 +54,10 @@
             "QS0000000008",
             "QT0000000007",
             "QW0000000002",
-    };
+            "XS0000000009", };
 
-    private final String[] invalidFormat = {
-            null,
-            "",                        // empty
-            "   ",                     // empty
+    private final String[] invalidFormat = { null, "", // empty
+            "   ", // empty
             "US037833100O", // proper check digit is '5', see above
             "BMG8571G109D", // proper check digit is '6', see above
             "AU0000XVGZAD", // proper check digit is '3', see above
@@ -68,41 +67,40 @@
             "3133EHHF3", // see VALIDATOR-422 Valid check-digit, but not valid ISIN
             "AU0000xvgzA3", // disallow lower case NSIN
             "gb0002634946", // disallow lower case ISO code
-            };
+    };
 
     // Invalid codes if country checking is enabled
-    private final String[] invalidFormatTrue = {
-            "AA0000000006", // Invalid country code
-            };
+    private final String[] invalidFormatTrue = { "AA0000000006", // Invalid country code
+    };
 
-    public ISINValidatorTest(final String name) {
-        super(name);
-    }
-
-    public void testIsValidTrue() {
-        for(final String f : validFormat) {
-            assertTrue(f, VALIDATOR_TRUE.isValid(f));
-        }
-    }
-
-    public void testInvalidTrue() {
-        for(final String f : invalidFormat) {
-            assertFalse(f, VALIDATOR_TRUE.isValid(f));
-        }
-        for(final String f : invalidFormatTrue) {
-            assertFalse(f, VALIDATOR_TRUE.isValid(f));
-        }
-    }
-
-    public void testIsValidFalse() {
-        for(final String f : validFormat) {
-            assertTrue(f, VALIDATOR_FALSE.isValid(f));
-        }
-    }
-
+    @Test
     public void testInvalidFalse() {
-        for(final String f : invalidFormat) {
-            assertFalse(f, VALIDATOR_FALSE.isValid(f));
+        for (final String f : invalidFormat) {
+            assertFalse(VALIDATOR_FALSE.isValid(f), f);
+        }
+    }
+
+    @Test
+    public void testInvalidTrue() {
+        for (final String f : invalidFormat) {
+            assertFalse(VALIDATOR_TRUE.isValid(f), f);
+        }
+        for (final String f : invalidFormatTrue) {
+            assertFalse(VALIDATOR_TRUE.isValid(f), f);
+        }
+    }
+
+    @Test
+    public void testIsValidFalse() {
+        for (final String f : validFormat) {
+            assertTrue(VALIDATOR_FALSE.isValid(f), f);
+        }
+    }
+
+    @Test
+    public void testIsValidTrue() {
+        for (final String f : validFormat) {
+            assertTrue(VALIDATOR_TRUE.isValid(f), f);
         }
     }
 
diff --git a/src/test/java/org/apache/commons/validator/routines/ISSNValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/ISSNValidatorTest.java
index bdcd056..a0872d4 100644
--- a/src/test/java/org/apache/commons/validator/routines/ISSNValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/ISSNValidatorTest.java
@@ -16,90 +16,126 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.util.Random;
 
 import org.apache.commons.validator.routines.checkdigit.CheckDigit;
 import org.apache.commons.validator.routines.checkdigit.EAN13CheckDigit;
-
-import junit.framework.TestCase;
+import org.junit.jupiter.api.Test;
 
 /**
- * ISSNValidator Test Case.
- *
- * @since 1.5.0
+ * Tests {@link ISSNValidator}.
  */
-public class ISSNValidatorTest extends TestCase {
+public class ISSNValidatorTest {
 
     private static final ISSNValidator VALIDATOR = ISSNValidator.getInstance();
 
-    private final String[] validFormat = {
-            "ISSN 0317-8471",
-            "1050-124X",
-            "ISSN 1562-6865",
-            "1063-7710",
-            "1748-7188",
-            "ISSN 0264-2875",
-            "1750-0095",
-            "1188-1534",
-            "1911-1479",
-            "ISSN 1911-1460",
-            "0001-6772",
-            "1365-201X",
-            "0264-3596",
-            "1144-875X",
-            };
+    private final String[] validFormat = { "ISSN 0317-8471", "1050-124X", "ISSN 1562-6865", "1063-7710", "1748-7188", "ISSN 0264-2875", "1750-0095",
+            "1188-1534", "1911-1479", "ISSN 1911-1460", "0001-6772", "1365-201X", "0264-3596", "1144-875X", };
 
-    private final String[] invalidFormat = {
-            "",                        // empty
-            "   ",                     // empty
-            "ISBN 0317-8471",          // wrong prefix
-            "'1050-124X",              // leading garbage
-            "ISSN1562-6865",           // missing separator
-            "10637710",                // missing separator
-            "1748-7188'",              // trailing garbage
-            "ISSN  0264-2875",         // extra space
-            "1750 0095",               // invalid separator
-            "1188_1534",               // invalid separator
-            "1911-1478",               // invalid checkdigit
-            };
+    private final String[] invalidFormat = { "", // empty
+            "   ", // empty
+            "ISBN 0317-8471", // wrong prefix
+            "'1050-124X", // leading garbage
+            "ISSN1562-6865", // missing separator
+            "10637710", // missing separator
+            "1748-7188'", // trailing garbage
+            "ISSN  0264-2875", // extra space
+            "1750 0095", // invalid separator
+            "1188_1534", // invalid separator
+            "1911-1478", // invalid checkdigit
+    };
 
     /**
-     * Create a test case with the specified name.
-     * @param name The name of the test
+     * Test Invalid EAN-13 ISSN prefix codes Test Input length
      */
-    public ISSNValidatorTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Test isValid() ISSN codes
-     */
-    public void testIsValidISSN() {
-        for(final String f : validFormat) {
-            assertTrue(f, VALIDATOR.isValid(f));
+    @Test
+    public void testConversionErrors() {
+        String input = null;
+        try {
+            input = "9780072129519";
+            VALIDATOR.extractFromEAN13(input);
+            fail("Expected IllegalArgumentException for '" + input + "'");
+        } catch (final IllegalArgumentException e) {
+            // expected result
         }
-    }
-
-    /**
-     * Test null values
-     */
-    public void testNull() {
-        assertFalse("isValid",  VALIDATOR.isValid(null));
+        try {
+            input = "9791090636071";
+            VALIDATOR.extractFromEAN13(input);
+            fail("Expected IllegalArgumentException for '" + input + "'");
+        } catch (final IllegalArgumentException e) {
+            // expected result
+        }
+        try {
+            input = "03178471";
+            VALIDATOR.extractFromEAN13(input);
+            fail("Expected IllegalArgumentException for '" + input + "'");
+        } catch (final IllegalArgumentException e) {
+            // expected result
+        }
     }
 
     /**
      * Test Invalid ISSN codes
      */
+    @Test
     public void testInvalid() {
-        for(final String f : invalidFormat) {
-            assertFalse(f, VALIDATOR.isValid(f));
+        for (final String f : invalidFormat) {
+            assertFalse(VALIDATOR.isValid(f), f);
         }
     }
 
+    /**
+     * Test valid EAN-13 ISSN codes and extract the ISSN
+     */
+    @Test
+    public void testIsValidExtract() {
+        assertEquals("12345679", VALIDATOR.extractFromEAN13("9771234567003"));
+        assertEquals("00014664", VALIDATOR.extractFromEAN13("9770001466006"));
+        assertEquals("03178471", VALIDATOR.extractFromEAN13("9770317847001"));
+        assertEquals("1144875X", VALIDATOR.extractFromEAN13("9771144875007"));
+    }
+
+    /**
+     * Test isValid() ISSN codes
+     */
+    @Test
+    public void testIsValidISSN() {
+        for (final String f : validFormat) {
+            assertTrue(VALIDATOR.isValid(f), f);
+        }
+    }
+
+    /**
+     * Test isValid() ISSN codes and convert them
+     */
+    @Test
+    public void testIsValidISSNConvert() {
+        final CheckDigit ean13cd = EAN13CheckDigit.EAN13_CHECK_DIGIT;
+        final Random r = new Random();
+        for (final String f : validFormat) {
+            final String suffix = String.format("%02d", r.nextInt(100));
+            final String ean13 = VALIDATOR.convertToEAN13(f, suffix);
+            assertTrue(ean13cd.isValid(ean13), ean13);
+        }
+        // internet samples
+        assertEquals(VALIDATOR.convertToEAN13("1144-875X", "00"), "9771144875007");
+        assertEquals(VALIDATOR.convertToEAN13("0264-3596", "00"), "9770264359008");
+        assertEquals(VALIDATOR.convertToEAN13("1234-5679", "00"), "9771234567003");
+    }
+
+    @Test
     public void testIsValidISSNConvertNull() {
         assertNull(VALIDATOR.convertToEAN13(null, "00"));
     }
 
+    @Test
     public void testIsValidISSNConvertSuffix() {
         try {
             assertNull(VALIDATOR.convertToEAN13(null, null));
@@ -140,54 +176,17 @@
     }
 
     /**
-     * Test isValid() ISSN codes and convert them
+     * Test null values
      */
-    public void testIsValidISSNConvert() {
-        final CheckDigit ean13cd = EAN13CheckDigit.EAN13_CHECK_DIGIT;
-        final Random r = new Random();
-        for(final String f : validFormat) {
-            final String suffix = String.format("%02d", r.nextInt(100));
-            final String ean13 = VALIDATOR.convertToEAN13(f, suffix);
-            assertTrue(ean13, ean13cd.isValid(ean13));
-        }
-        // internet samples
-        assertEquals("9771144875007", VALIDATOR.convertToEAN13("1144-875X", "00"));
-        assertEquals("9770264359008", VALIDATOR.convertToEAN13("0264-3596", "00"));
-        assertEquals("9771234567003", VALIDATOR.convertToEAN13("1234-5679", "00"));
-    }
-
-    /**
-     * Test Invalid EAN-13 ISSN prefix codes
-     * Test Input length
-     */
-    public void testConversionErrors() {
-        String input = null;
-        try {
-            input = "9780072129519";
-            VALIDATOR.extractFromEAN13(input);
-            fail("Expected IllegalArgumentException for '" + input + "'");
-        } catch (final IllegalArgumentException e) {
-            // expected result
-        }
-        try {
-            input = "9791090636071";
-            VALIDATOR.extractFromEAN13(input);
-            fail("Expected IllegalArgumentException for '" + input + "'");
-        } catch (final IllegalArgumentException e) {
-            // expected result
-        }
-        try {
-            input = "03178471";
-            VALIDATOR.extractFromEAN13(input);
-            fail("Expected IllegalArgumentException for '" + input + "'");
-        } catch (final IllegalArgumentException e) {
-            // expected result
-        }
+    @Test
+    public void testNull() {
+        assertFalse(VALIDATOR.isValid(null), "isValid");
     }
 
     /**
      * Test Invalid EAN-13 ISSN codes
      */
+    @Test
     public void testValidCheckDigitEan13() {
         assertNull(VALIDATOR.extractFromEAN13("9771234567001"));
         assertNull(VALIDATOR.extractFromEAN13("9771234567002"));
@@ -200,13 +199,4 @@
         assertNull(VALIDATOR.extractFromEAN13("9771234567009"));
         assertNull(VALIDATOR.extractFromEAN13("9771234567000"));
     }
-    /**
-     *  Test valid EAN-13 ISSN codes and extract the ISSN
-     */
-    public void testIsValidExtract() {
-        assertEquals("12345679", VALIDATOR.extractFromEAN13("9771234567003"));
-        assertEquals("00014664", VALIDATOR.extractFromEAN13("9770001466006"));
-        assertEquals("03178471", VALIDATOR.extractFromEAN13("9770317847001"));
-        assertEquals("1144875X", VALIDATOR.extractFromEAN13("9771144875007"));
-    }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/InetAddressValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/InetAddressValidatorTest.java
index 7200e8d..35741ff 100644
--- a/src/test/java/org/apache/commons/validator/routines/InetAddressValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/InetAddressValidatorTest.java
@@ -17,634 +17,665 @@
 
 package org.apache.commons.validator.routines;
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * Test cases for InetAddressValidator.
  */
-public class InetAddressValidatorTest extends TestCase {
+public class InetAddressValidatorTest {
 
     private InetAddressValidator validator;
 
-    /**
-     * Constructor.
-     * @param name
-     */
-    public InetAddressValidatorTest(final String name) {
-        super(name);
-    }
-
-    @Override
+    @BeforeEach
     protected void setUp() {
         validator = new InetAddressValidator();
     }
 
     /**
-     * Test IPs that point to real, well-known hosts (without actually looking them up).
+     * Test obviously broken IPs.
      */
-    public void testInetAddressesFromTheWild() {
-        assertTrue("www.apache.org IP should be valid",       validator.isValid("140.211.11.130"));
-        assertTrue("www.l.google.com IP should be valid",     validator.isValid("72.14.253.103"));
-        assertTrue("fsf.org IP should be valid",              validator.isValid("199.232.41.5"));
-        assertTrue("appscs.ign.com IP should be valid",       validator.isValid("216.35.123.87"));
-    }
-
-    public void testVALIDATOR_335() {
-        assertTrue("2001:0438:FFFE:0000:0000:0000:0000:0A35 should be valid",       validator.isValid("2001:0438:FFFE:0000:0000:0000:0000:0A35"));
-    }
-
-    public void testVALIDATOR_419() {
-        String addr;
-        addr = "0:0:0:0:0:0:13.1.68.3";
-        assertTrue(addr, validator.isValid(addr));
-        addr = "0:0:0:0:0:FFFF:129.144.52.38";
-        assertTrue(addr, validator.isValid(addr));
-        addr = "::13.1.68.3";
-        assertTrue(addr, validator.isValid(addr));
-        addr = "::FFFF:129.144.52.38";
-        assertTrue(addr, validator.isValid(addr));
-
-        addr = "::ffff:192.168.1.1:192.168.1.1";
-        assertFalse(addr, validator.isValid(addr));
-        addr = "::192.168.1.1:192.168.1.1";
-        assertFalse(addr, validator.isValid(addr));
-    }
-
-    /**
-     * Inet6Address may also contain a scope id
-     */
-    public void testVALIDATOR_445() {
-        final String [] valid = {
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876",
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/123",
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/0",
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876%0",
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abcdefgh",
-            };
-        final String [] invalid = {
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/129", // too big
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/-0", // sign not allowed
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/+0", // sign not allowed
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/10O", // non-digit
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876/0%0", // /bits before %node-id
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abc defgh", // space in node id
-            "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abc%defgh", // '%' in node id
-            };
-        for(final String item : valid) {
-            assertTrue(String.format("%s should be valid", item), validator.isValid(item));
-        }
-        for(final String item : invalid) {
-            assertFalse(String.format("%s should be invalid", item), validator.isValid(item));
-        }
+    @Test
+    public void testBrokenInetAddresses() {
+        assertFalse(validator.isValid("124.14.32.abc"), "IP with characters should be invalid");
+        // TODO: there is some debate as to whether leading zeros should be allowed
+        // They are ambiguous: does the leading 0 mean octal?
+        assertFalse(validator.isValid("124.14.32.01"), "IP with leading zeroes should be invalid");
+        assertFalse(validator.isValid("23.64.12"), "IP with three groups should be invalid");
+        assertFalse(validator.isValid("26.34.23.77.234"), "IP with five groups should be invalid");
+        assertFalse(validator.isValidInet6Address(""), "IP empty string should be invalid"); // empty string
     }
 
     /**
      * Test valid and invalid IPs from each address class.
      */
+    @Test
     public void testInetAddressesByClass() {
-        assertTrue("class A IP should be valid",              validator.isValid("24.25.231.12"));
-        assertFalse("illegal class A IP should be invalid",   validator.isValid("2.41.32.324"));
+        assertTrue(validator.isValid("24.25.231.12"), "class A IP should be valid");
+        assertFalse(validator.isValid("2.41.32.324"), "illegal class A IP should be invalid");
 
-        assertTrue("class B IP should be valid",              validator.isValid("135.14.44.12"));
-        assertFalse("illegal class B IP should be invalid",   validator.isValid("154.123.441.123"));
+        assertTrue(validator.isValid("135.14.44.12"), "class B IP should be valid");
+        assertFalse(validator.isValid("154.123.441.123"), "illegal class B IP should be invalid");
 
-        assertTrue("class C IP should be valid",              validator.isValid("213.25.224.32"));
-        assertFalse("illegal class C IP should be invalid",   validator.isValid("201.543.23.11"));
+        assertTrue(validator.isValid("213.25.224.32"), "class C IP should be valid");
+        assertFalse(validator.isValid("201.543.23.11"), "illegal class C IP should be invalid");
 
-        assertTrue("class D IP should be valid",              validator.isValid("229.35.159.6"));
-        assertFalse("illegal class D IP should be invalid",   validator.isValid("231.54.11.987"));
+        assertTrue(validator.isValid("229.35.159.6"), "class D IP should be valid");
+        assertFalse(validator.isValid("231.54.11.987"), "illegal class D IP should be invalid");
 
-        assertTrue("class E IP should be valid",              validator.isValid("248.85.24.92"));
-        assertFalse("illegal class E IP should be invalid",   validator.isValid("250.21.323.48"));
+        assertTrue(validator.isValid("248.85.24.92"), "class E IP should be valid");
+        assertFalse(validator.isValid("250.21.323.48"), "illegal class E IP should be invalid");
+    }
+
+    /**
+     * Test IPs that point to real, well-known hosts (without actually looking them up).
+     */
+    @Test
+    public void testInetAddressesFromTheWild() {
+        assertTrue(validator.isValid("140.211.11.130"), "www.apache.org IP should be valid");
+        assertTrue(validator.isValid("72.14.253.103"), "www.l.google.com IP should be valid");
+        assertTrue(validator.isValid("199.232.41.5"), "fsf.org IP should be valid");
+        assertTrue(validator.isValid("216.35.123.87"), "appscs.ign.com IP should be valid");
+    }
+
+    /**
+     * Test IPv6 addresses.
+     * <p>
+     * These tests were ported from a <a href="https://download.dartware.com/thirdparty/test-ipv6-regex.pl">Perl script</a>.
+     * </p>
+     */
+    @Test
+    public void testIPv6() {
+        // The original Perl script contained a lot of duplicate tests.
+        // I removed the duplicates I noticed, but there may be more.
+        assertFalse(validator.isValidInet6Address(""), "IPV6 empty string should be invalid"); // empty string
+        assertTrue(validator.isValidInet6Address("::1"), "IPV6 ::1 should be valid"); // loopback, compressed, non-routable
+        assertTrue(validator.isValidInet6Address("::"), "IPV6 :: should be valid"); // unspecified, compressed, non-routable
+        assertTrue(validator.isValidInet6Address("0:0:0:0:0:0:0:1"), "IPV6 0:0:0:0:0:0:0:1 should be valid"); // loopback, full
+        assertTrue(validator.isValidInet6Address("0:0:0:0:0:0:0:0"), "IPV6 0:0:0:0:0:0:0:0 should be valid"); // unspecified, full
+        assertTrue(validator.isValidInet6Address("2001:DB8:0:0:8:800:200C:417A"), "IPV6 2001:DB8:0:0:8:800:200C:417A should be valid"); // unicast, full
+        assertTrue(validator.isValidInet6Address("FF01:0:0:0:0:0:0:101"), "IPV6 FF01:0:0:0:0:0:0:101 should be valid"); // multicast, full
+        assertTrue(validator.isValidInet6Address("2001:DB8::8:800:200C:417A"), "IPV6 2001:DB8::8:800:200C:417A should be valid"); // unicast, compressed
+        assertTrue(validator.isValidInet6Address("FF01::101"), "IPV6 FF01::101 should be valid"); // multicast, compressed
+        assertFalse(validator.isValidInet6Address("2001:DB8:0:0:8:800:200C:417A:221"), "IPV6 2001:DB8:0:0:8:800:200C:417A:221 should be invalid"); // unicast,
+                                                                                                                                                   // full
+        assertFalse(validator.isValidInet6Address("FF01::101::2"), "IPV6 FF01::101::2 should be invalid"); // multicast, compressed
+        assertTrue(validator.isValidInet6Address("fe80::217:f2ff:fe07:ed62"), "IPV6 fe80::217:f2ff:fe07:ed62 should be valid");
+        assertTrue(validator.isValidInet6Address("2001:0000:1234:0000:0000:C1C0:ABCD:0876"), "IPV6 2001:0000:1234:0000:0000:C1C0:ABCD:0876 should be valid");
+        assertTrue(validator.isValidInet6Address("3ffe:0b00:0000:0000:0001:0000:0000:000a"), "IPV6 3ffe:0b00:0000:0000:0001:0000:0000:000a should be valid");
+        assertTrue(validator.isValidInet6Address("FF02:0000:0000:0000:0000:0000:0000:0001"), "IPV6 FF02:0000:0000:0000:0000:0000:0000:0001 should be valid");
+        assertTrue(validator.isValidInet6Address("0000:0000:0000:0000:0000:0000:0000:0001"), "IPV6 0000:0000:0000:0000:0000:0000:0000:0001 should be valid");
+        assertTrue(validator.isValidInet6Address("0000:0000:0000:0000:0000:0000:0000:0000"), "IPV6 0000:0000:0000:0000:0000:0000:0000:0000 should be valid");
+        assertFalse(validator.isValidInet6Address("02001:0000:1234:0000:0000:C1C0:ABCD:0876"),
+                "IPV6 02001:0000:1234:0000:0000:C1C0:ABCD:0876 should be invalid"); // extra 0 not allowed!
+        assertFalse(validator.isValidInet6Address("2001:0000:1234:0000:00001:C1C0:ABCD:0876"),
+                "IPV6 2001:0000:1234:0000:00001:C1C0:ABCD:0876 should be invalid"); // extra 0 not allowed!
+        assertFalse(validator.isValidInet6Address("2001:0000:1234:0000:0000:C1C0:ABCD:0876 0"),
+                "IPV6 2001:0000:1234:0000:0000:C1C0:ABCD:0876 0 should be invalid"); // junk after valid address
+        assertFalse(validator.isValidInet6Address("2001:0000:1234: 0000:0000:C1C0:ABCD:0876"),
+                "IPV6 2001:0000:1234: 0000:0000:C1C0:ABCD:0876 should be invalid"); // internal space
+        assertFalse(validator.isValidInet6Address("3ffe:0b00:0000:0001:0000:0000:000a"), "IPV6 3ffe:0b00:0000:0001:0000:0000:000a should be invalid"); // seven
+                                                                                                                                                       // segments
+        assertFalse(validator.isValidInet6Address("FF02:0000:0000:0000:0000:0000:0000:0000:0001"),
+                "IPV6 FF02:0000:0000:0000:0000:0000:0000:0000:0001 should be invalid"); // nine segments
+        assertFalse(validator.isValidInet6Address("3ffe:b00::1::a"), "IPV6 3ffe:b00::1::a should be invalid"); // double "::"
+        assertFalse(validator.isValidInet6Address("::1111:2222:3333:4444:5555:6666::"), "IPV6 ::1111:2222:3333:4444:5555:6666:: should be invalid"); // double
+                                                                                                                                                     // "::"
+        assertTrue(validator.isValidInet6Address("2::10"), "IPV6 2::10 should be valid");
+        assertTrue(validator.isValidInet6Address("ff02::1"), "IPV6 ff02::1 should be valid");
+        assertTrue(validator.isValidInet6Address("fe80::"), "IPV6 fe80:: should be valid");
+        assertTrue(validator.isValidInet6Address("2002::"), "IPV6 2002:: should be valid");
+        assertTrue(validator.isValidInet6Address("2001:db8::"), "IPV6 2001:db8:: should be valid");
+        assertTrue(validator.isValidInet6Address("2001:0db8:1234::"), "IPV6 2001:0db8:1234:: should be valid");
+        assertTrue(validator.isValidInet6Address("::ffff:0:0"), "IPV6 ::ffff:0:0 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4:5:6:7:8"), "IPV6 1:2:3:4:5:6:7:8 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4:5:6::8"), "IPV6 1:2:3:4:5:6::8 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4:5::8"), "IPV6 1:2:3:4:5::8 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4::8"), "IPV6 1:2:3:4::8 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3::8"), "IPV6 1:2:3::8 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2::8"), "IPV6 1:2::8 should be valid");
+        assertTrue(validator.isValidInet6Address("1::8"), "IPV6 1::8 should be valid");
+        assertTrue(validator.isValidInet6Address("1::2:3:4:5:6:7"), "IPV6 1::2:3:4:5:6:7 should be valid");
+        assertTrue(validator.isValidInet6Address("1::2:3:4:5:6"), "IPV6 1::2:3:4:5:6 should be valid");
+        assertTrue(validator.isValidInet6Address("1::2:3:4:5"), "IPV6 1::2:3:4:5 should be valid");
+        assertTrue(validator.isValidInet6Address("1::2:3:4"), "IPV6 1::2:3:4 should be valid");
+        assertTrue(validator.isValidInet6Address("1::2:3"), "IPV6 1::2:3 should be valid");
+        assertTrue(validator.isValidInet6Address("::2:3:4:5:6:7:8"), "IPV6 ::2:3:4:5:6:7:8 should be valid");
+        assertTrue(validator.isValidInet6Address("::2:3:4:5:6:7"), "IPV6 ::2:3:4:5:6:7 should be valid");
+        assertTrue(validator.isValidInet6Address("::2:3:4:5:6"), "IPV6 ::2:3:4:5:6 should be valid");
+        assertTrue(validator.isValidInet6Address("::2:3:4:5"), "IPV6 ::2:3:4:5 should be valid");
+        assertTrue(validator.isValidInet6Address("::2:3:4"), "IPV6 ::2:3:4 should be valid");
+        assertTrue(validator.isValidInet6Address("::2:3"), "IPV6 ::2:3 should be valid");
+        assertTrue(validator.isValidInet6Address("::8"), "IPV6 ::8 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4:5:6::"), "IPV6 1:2:3:4:5:6:: should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4:5::"), "IPV6 1:2:3:4:5:: should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4::"), "IPV6 1:2:3:4:: should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3::"), "IPV6 1:2:3:: should be valid");
+        assertTrue(validator.isValidInet6Address("1:2::"), "IPV6 1:2:: should be valid");
+        assertTrue(validator.isValidInet6Address("1::"), "IPV6 1:: should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4:5::7:8"), "IPV6 1:2:3:4:5::7:8 should be valid");
+        assertFalse(validator.isValidInet6Address("1:2:3::4:5::7:8"), "IPV6 1:2:3::4:5::7:8 should be invalid"); // Double "::"
+        assertFalse(validator.isValidInet6Address("12345::6:7:8"), "IPV6 12345::6:7:8 should be invalid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4::7:8"), "IPV6 1:2:3:4::7:8 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3::7:8"), "IPV6 1:2:3::7:8 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2::7:8"), "IPV6 1:2::7:8 should be valid");
+        assertTrue(validator.isValidInet6Address("1::7:8"), "IPV6 1::7:8 should be valid");
+        // IPv4 addresses as dotted-quads
+        assertTrue(validator.isValidInet6Address("1:2:3:4:5:6:1.2.3.4"), "IPV6 1:2:3:4:5:6:1.2.3.4 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4:5::1.2.3.4"), "IPV6 1:2:3:4:5::1.2.3.4 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4::1.2.3.4"), "IPV6 1:2:3:4::1.2.3.4 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3::1.2.3.4"), "IPV6 1:2:3::1.2.3.4 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2::1.2.3.4"), "IPV6 1:2::1.2.3.4 should be valid");
+        assertTrue(validator.isValidInet6Address("1::1.2.3.4"), "IPV6 1::1.2.3.4 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3:4::5:1.2.3.4"), "IPV6 1:2:3:4::5:1.2.3.4 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2:3::5:1.2.3.4"), "IPV6 1:2:3::5:1.2.3.4 should be valid");
+        assertTrue(validator.isValidInet6Address("1:2::5:1.2.3.4"), "IPV6 1:2::5:1.2.3.4 should be valid");
+        assertTrue(validator.isValidInet6Address("1::5:1.2.3.4"), "IPV6 1::5:1.2.3.4 should be valid");
+        assertTrue(validator.isValidInet6Address("1::5:11.22.33.44"), "IPV6 1::5:11.22.33.44 should be valid");
+        assertFalse(validator.isValidInet6Address("1::5:400.2.3.4"), "IPV6 1::5:400.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:260.2.3.4"), "IPV6 1::5:260.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:256.2.3.4"), "IPV6 1::5:256.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:1.256.3.4"), "IPV6 1::5:1.256.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:1.2.256.4"), "IPV6 1::5:1.2.256.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:1.2.3.256"), "IPV6 1::5:1.2.3.256 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:300.2.3.4"), "IPV6 1::5:300.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:1.300.3.4"), "IPV6 1::5:1.300.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:1.2.300.4"), "IPV6 1::5:1.2.300.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:1.2.3.300"), "IPV6 1::5:1.2.3.300 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:900.2.3.4"), "IPV6 1::5:900.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:1.900.3.4"), "IPV6 1::5:1.900.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:1.2.900.4"), "IPV6 1::5:1.2.900.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:1.2.3.900"), "IPV6 1::5:1.2.3.900 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:300.300.300.300"), "IPV6 1::5:300.300.300.300 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::5:3000.30.30.30"), "IPV6 1::5:3000.30.30.30 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::400.2.3.4"), "IPV6 1::400.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::260.2.3.4"), "IPV6 1::260.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::256.2.3.4"), "IPV6 1::256.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::1.256.3.4"), "IPV6 1::1.256.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::1.2.256.4"), "IPV6 1::1.2.256.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::1.2.3.256"), "IPV6 1::1.2.3.256 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::300.2.3.4"), "IPV6 1::300.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::1.300.3.4"), "IPV6 1::1.300.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::1.2.300.4"), "IPV6 1::1.2.300.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::1.2.3.300"), "IPV6 1::1.2.3.300 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::900.2.3.4"), "IPV6 1::900.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::1.900.3.4"), "IPV6 1::1.900.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::1.2.900.4"), "IPV6 1::1.2.900.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::1.2.3.900"), "IPV6 1::1.2.3.900 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::300.300.300.300"), "IPV6 1::300.300.300.300 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::3000.30.30.30"), "IPV6 1::3000.30.30.30 should be invalid");
+        assertFalse(validator.isValidInet6Address("::400.2.3.4"), "IPV6 ::400.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::260.2.3.4"), "IPV6 ::260.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::256.2.3.4"), "IPV6 ::256.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::1.256.3.4"), "IPV6 ::1.256.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::1.2.256.4"), "IPV6 ::1.2.256.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::1.2.3.256"), "IPV6 ::1.2.3.256 should be invalid");
+        assertFalse(validator.isValidInet6Address("::300.2.3.4"), "IPV6 ::300.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::1.300.3.4"), "IPV6 ::1.300.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::1.2.300.4"), "IPV6 ::1.2.300.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::1.2.3.300"), "IPV6 ::1.2.3.300 should be invalid");
+        assertFalse(validator.isValidInet6Address("::900.2.3.4"), "IPV6 ::900.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::1.900.3.4"), "IPV6 ::1.900.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::1.2.900.4"), "IPV6 ::1.2.900.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::1.2.3.900"), "IPV6 ::1.2.3.900 should be invalid");
+        assertFalse(validator.isValidInet6Address("::300.300.300.300"), "IPV6 ::300.300.300.300 should be invalid");
+        assertFalse(validator.isValidInet6Address("::3000.30.30.30"), "IPV6 ::3000.30.30.30 should be invalid");
+        assertTrue(validator.isValidInet6Address("fe80::217:f2ff:254.7.237.98"), "IPV6 fe80::217:f2ff:254.7.237.98 should be valid");
+        assertTrue(validator.isValidInet6Address("::ffff:192.168.1.26"), "IPV6 ::ffff:192.168.1.26 should be valid");
+        assertFalse(validator.isValidInet6Address("2001:1:1:1:1:1:255Z255X255Y255"), "IPV6 2001:1:1:1:1:1:255Z255X255Y255 should be invalid"); // garbage
+                                                                                                                                               // instead of "."
+                                                                                                                                               // in IPv4
+        assertFalse(validator.isValidInet6Address("::ffff:192x168.1.26"), "IPV6 ::ffff:192x168.1.26 should be invalid"); // ditto
+        assertTrue(validator.isValidInet6Address("::ffff:192.168.1.1"), "IPV6 ::ffff:192.168.1.1 should be valid");
+        assertTrue(validator.isValidInet6Address("0:0:0:0:0:0:13.1.68.3"), "IPV6 0:0:0:0:0:0:13.1.68.3 should be valid"); // IPv4-compatible IPv6 address, full,
+                                                                                                                          // deprecated
+        assertTrue(validator.isValidInet6Address("0:0:0:0:0:FFFF:129.144.52.38"), "IPV6 0:0:0:0:0:FFFF:129.144.52.38 should be valid"); // IPv4-mapped IPv6
+                                                                                                                                        // address, full
+        assertTrue(validator.isValidInet6Address("::13.1.68.3"), "IPV6 ::13.1.68.3 should be valid"); // IPv4-compatible IPv6 address, compressed, deprecated
+        assertTrue(validator.isValidInet6Address("::FFFF:129.144.52.38"), "IPV6 ::FFFF:129.144.52.38 should be valid"); // IPv4-mapped IPv6 address, compressed
+        assertTrue(validator.isValidInet6Address("fe80:0:0:0:204:61ff:254.157.241.86"), "IPV6 fe80:0:0:0:204:61ff:254.157.241.86 should be valid");
+        assertTrue(validator.isValidInet6Address("fe80::204:61ff:254.157.241.86"), "IPV6 fe80::204:61ff:254.157.241.86 should be valid");
+        assertTrue(validator.isValidInet6Address("::ffff:12.34.56.78"), "IPV6 ::ffff:12.34.56.78 should be valid");
+        assertFalse(validator.isValidInet6Address("::ffff:2.3.4"), "IPV6 ::ffff:2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::ffff:257.1.2.3"), "IPV6 ::ffff:257.1.2.3 should be invalid");
+        assertFalse(validator.isValidInet6Address("1.2.3.4"), "IPV6 1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1.2.3.4:1111:2222:3333:4444::5555"), "IPV6 1.2.3.4:1111:2222:3333:4444::5555 should be invalid");
+        assertFalse(validator.isValidInet6Address("1.2.3.4:1111:2222:3333::5555"), "IPV6 1.2.3.4:1111:2222:3333::5555 should be invalid");
+        assertFalse(validator.isValidInet6Address("1.2.3.4:1111:2222::5555"), "IPV6 1.2.3.4:1111:2222::5555 should be invalid");
+        assertFalse(validator.isValidInet6Address("1.2.3.4:1111::5555"), "IPV6 1.2.3.4:1111::5555 should be invalid");
+        assertFalse(validator.isValidInet6Address("1.2.3.4::5555"), "IPV6 1.2.3.4::5555 should be invalid");
+        assertFalse(validator.isValidInet6Address("1.2.3.4::"), "IPV6 1.2.3.4:: should be invalid");
+        // Testing IPv4 addresses represented as dotted-quads
+        // Leading zeroes in IPv4 addresses not allowed: some systems treat the leading "0" in ".086" as the start of an octal number
+        // Update: The BNF in RFC-3986 explicitly defines the dec-octet (for IPv4 addresses) not to have a leading zero
+        assertFalse(validator.isValidInet6Address("fe80:0000:0000:0000:0204:61ff:254.157.241.086"),
+                "IPV6 fe80:0000:0000:0000:0204:61ff:254.157.241.086 should be invalid");
+        assertTrue(validator.isValidInet6Address("::ffff:192.0.2.128"), "IPV6 ::ffff:192.0.2.128 should be valid"); // but this is OK, since there's a single
+                                                                                                                    // digit
+        assertFalse(validator.isValidInet6Address("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4"), "IPV6 XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:00.00.00.00"),
+                "IPV6 1111:2222:3333:4444:5555:6666:00.00.00.00 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:000.000.000.000"),
+                "IPV6 1111:2222:3333:4444:5555:6666:000.000.000.000 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:256.256.256.256"),
+                "IPV6 1111:2222:3333:4444:5555:6666:256.256.256.256 should be invalid");
+        assertTrue(validator.isValidInet6Address("fe80:0000:0000:0000:0204:61ff:fe9d:f156"), "IPV6 fe80:0000:0000:0000:0204:61ff:fe9d:f156 should be valid");
+        assertTrue(validator.isValidInet6Address("fe80:0:0:0:204:61ff:fe9d:f156"), "IPV6 fe80:0:0:0:204:61ff:fe9d:f156 should be valid");
+        assertTrue(validator.isValidInet6Address("fe80::204:61ff:fe9d:f156"), "IPV6 fe80::204:61ff:fe9d:f156 should be valid");
+        assertFalse(validator.isValidInet6Address(":"), "IPV6 : should be invalid");
+        assertTrue(validator.isValidInet6Address("::ffff:c000:280"), "IPV6 ::ffff:c000:280 should be valid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444::5555:"), "IPV6 1111:2222:3333:4444::5555: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333::5555:"), "IPV6 1111:2222:3333::5555: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::5555:"), "IPV6 1111:2222::5555: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::5555:"), "IPV6 1111::5555: should be invalid");
+        assertFalse(validator.isValidInet6Address("::5555:"), "IPV6 ::5555: should be invalid");
+        assertFalse(validator.isValidInet6Address(":::"), "IPV6 ::: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:"), "IPV6 1111: should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444::5555"), "IPV6 :1111:2222:3333:4444::5555 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333::5555"), "IPV6 :1111:2222:3333::5555 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222::5555"), "IPV6 :1111:2222::5555 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::5555"), "IPV6 :1111::5555 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::5555"), "IPV6 :::5555 should be invalid");
+        assertTrue(validator.isValidInet6Address("2001:0db8:85a3:0000:0000:8a2e:0370:7334"), "IPV6 2001:0db8:85a3:0000:0000:8a2e:0370:7334 should be valid");
+        assertTrue(validator.isValidInet6Address("2001:db8:85a3:0:0:8a2e:370:7334"), "IPV6 2001:db8:85a3:0:0:8a2e:370:7334 should be valid");
+        assertTrue(validator.isValidInet6Address("2001:db8:85a3::8a2e:370:7334"), "IPV6 2001:db8:85a3::8a2e:370:7334 should be valid");
+        assertTrue(validator.isValidInet6Address("2001:0db8:0000:0000:0000:0000:1428:57ab"), "IPV6 2001:0db8:0000:0000:0000:0000:1428:57ab should be valid");
+        assertTrue(validator.isValidInet6Address("2001:0db8:0000:0000:0000::1428:57ab"), "IPV6 2001:0db8:0000:0000:0000::1428:57ab should be valid");
+        assertTrue(validator.isValidInet6Address("2001:0db8:0:0:0:0:1428:57ab"), "IPV6 2001:0db8:0:0:0:0:1428:57ab should be valid");
+        assertTrue(validator.isValidInet6Address("2001:0db8:0:0::1428:57ab"), "IPV6 2001:0db8:0:0::1428:57ab should be valid");
+        assertTrue(validator.isValidInet6Address("2001:0db8::1428:57ab"), "IPV6 2001:0db8::1428:57ab should be valid");
+        assertTrue(validator.isValidInet6Address("2001:db8::1428:57ab"), "IPV6 2001:db8::1428:57ab should be valid");
+        assertTrue(validator.isValidInet6Address("::ffff:0c22:384e"), "IPV6 ::ffff:0c22:384e should be valid");
+        assertTrue(validator.isValidInet6Address("2001:0db8:1234:0000:0000:0000:0000:0000"), "IPV6 2001:0db8:1234:0000:0000:0000:0000:0000 should be valid");
+        assertTrue(validator.isValidInet6Address("2001:0db8:1234:ffff:ffff:ffff:ffff:ffff"), "IPV6 2001:0db8:1234:ffff:ffff:ffff:ffff:ffff should be valid");
+        assertTrue(validator.isValidInet6Address("2001:db8:a::123"), "IPV6 2001:db8:a::123 should be valid");
+        assertFalse(validator.isValidInet6Address("123"), "IPV6 123 should be invalid");
+        assertFalse(validator.isValidInet6Address("ldkfj"), "IPV6 ldkfj should be invalid");
+        assertFalse(validator.isValidInet6Address("2001::FFD3::57ab"), "IPV6 2001::FFD3::57ab should be invalid");
+        assertFalse(validator.isValidInet6Address("2001:db8:85a3::8a2e:37023:7334"), "IPV6 2001:db8:85a3::8a2e:37023:7334 should be invalid");
+        assertFalse(validator.isValidInet6Address("2001:db8:85a3::8a2e:370k:7334"), "IPV6 2001:db8:85a3::8a2e:370k:7334 should be invalid");
+        assertFalse(validator.isValidInet6Address("1:2:3:4:5:6:7:8:9"), "IPV6 1:2:3:4:5:6:7:8:9 should be invalid");
+        assertFalse(validator.isValidInet6Address("1::2::3"), "IPV6 1::2::3 should be invalid");
+        assertFalse(validator.isValidInet6Address("1:::3:4:5"), "IPV6 1:::3:4:5 should be invalid");
+        assertFalse(validator.isValidInet6Address("1:2:3::4:5:6:7:8:9"), "IPV6 1:2:3::4:5:6:7:8:9 should be invalid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888"), "IPV6 1111:2222:3333:4444:5555:6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777::"), "IPV6 1111:2222:3333:4444:5555:6666:7777:: should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666::"), "IPV6 1111:2222:3333:4444:5555:6666:: should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444:5555::"), "IPV6 1111:2222:3333:4444:5555:: should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444::"), "IPV6 1111:2222:3333:4444:: should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333::"), "IPV6 1111:2222:3333:: should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222::"), "IPV6 1111:2222:: should be valid");
+        assertTrue(validator.isValidInet6Address("1111::"), "IPV6 1111:: should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666::8888"), "IPV6 1111:2222:3333:4444:5555:6666::8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444:5555::8888"), "IPV6 1111:2222:3333:4444:5555::8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444::8888"), "IPV6 1111:2222:3333:4444::8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333::8888"), "IPV6 1111:2222:3333::8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222::8888"), "IPV6 1111:2222::8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111::8888"), "IPV6 1111::8888 should be valid");
+        assertTrue(validator.isValidInet6Address("::8888"), "IPV6 ::8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444:5555::7777:8888"), "IPV6 1111:2222:3333:4444:5555::7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444::7777:8888"), "IPV6 1111:2222:3333:4444::7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333::7777:8888"), "IPV6 1111:2222:3333::7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222::7777:8888"), "IPV6 1111:2222::7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111::7777:8888"), "IPV6 1111::7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("::7777:8888"), "IPV6 ::7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444::6666:7777:8888"), "IPV6 1111:2222:3333:4444::6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333::6666:7777:8888"), "IPV6 1111:2222:3333::6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222::6666:7777:8888"), "IPV6 1111:2222::6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111::6666:7777:8888"), "IPV6 1111::6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("::6666:7777:8888"), "IPV6 ::6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333::5555:6666:7777:8888"), "IPV6 1111:2222:3333::5555:6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222::5555:6666:7777:8888"), "IPV6 1111:2222::5555:6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111::5555:6666:7777:8888"), "IPV6 1111::5555:6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("::5555:6666:7777:8888"), "IPV6 ::5555:6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222::4444:5555:6666:7777:8888"), "IPV6 1111:2222::4444:5555:6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111::4444:5555:6666:7777:8888"), "IPV6 1111::4444:5555:6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("::4444:5555:6666:7777:8888"), "IPV6 ::4444:5555:6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111::3333:4444:5555:6666:7777:8888"), "IPV6 1111::3333:4444:5555:6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("::3333:4444:5555:6666:7777:8888"), "IPV6 ::3333:4444:5555:6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888"), "IPV6 ::2222:3333:4444:5555:6666:7777:8888 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:123.123.123.123"),
+                "IPV6 1111:2222:3333:4444:5555:6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444:5555::123.123.123.123"),
+                "IPV6 1111:2222:3333:4444:5555::123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444::123.123.123.123"), "IPV6 1111:2222:3333:4444::123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333::123.123.123.123"), "IPV6 1111:2222:3333::123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222::123.123.123.123"), "IPV6 1111:2222::123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111::123.123.123.123"), "IPV6 1111::123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("::123.123.123.123"), "IPV6 ::123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333:4444::6666:123.123.123.123"),
+                "IPV6 1111:2222:3333:4444::6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333::6666:123.123.123.123"), "IPV6 1111:2222:3333::6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222::6666:123.123.123.123"), "IPV6 1111:2222::6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111::6666:123.123.123.123"), "IPV6 1111::6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("::6666:123.123.123.123"), "IPV6 ::6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222:3333::5555:6666:123.123.123.123"),
+                "IPV6 1111:2222:3333::5555:6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222::5555:6666:123.123.123.123"), "IPV6 1111:2222::5555:6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111::5555:6666:123.123.123.123"), "IPV6 1111::5555:6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("::5555:6666:123.123.123.123"), "IPV6 ::5555:6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111:2222::4444:5555:6666:123.123.123.123"),
+                "IPV6 1111:2222::4444:5555:6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111::4444:5555:6666:123.123.123.123"), "IPV6 1111::4444:5555:6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("::4444:5555:6666:123.123.123.123"), "IPV6 ::4444:5555:6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("1111::3333:4444:5555:6666:123.123.123.123"),
+                "IPV6 1111::3333:4444:5555:6666:123.123.123.123 should be valid");
+        assertTrue(validator.isValidInet6Address("::2222:3333:4444:5555:6666:123.123.123.123"),
+                "IPV6 ::2222:3333:4444:5555:6666:123.123.123.123 should be valid");
+        // Trying combinations of "0" and "::"
+        // These are all syntactically correct, but are bad form
+        // because "0" adjacent to "::" should be combined into "::"
+        assertTrue(validator.isValidInet6Address("::0:0:0:0:0:0:0"), "IPV6 ::0:0:0:0:0:0:0 should be valid");
+        assertTrue(validator.isValidInet6Address("::0:0:0:0:0:0"), "IPV6 ::0:0:0:0:0:0 should be valid");
+        assertTrue(validator.isValidInet6Address("::0:0:0:0:0"), "IPV6 ::0:0:0:0:0 should be valid");
+        assertTrue(validator.isValidInet6Address("::0:0:0:0"), "IPV6 ::0:0:0:0 should be valid");
+        assertTrue(validator.isValidInet6Address("::0:0:0"), "IPV6 ::0:0:0 should be valid");
+        assertTrue(validator.isValidInet6Address("::0:0"), "IPV6 ::0:0 should be valid");
+        assertTrue(validator.isValidInet6Address("::0"), "IPV6 ::0 should be valid");
+        assertTrue(validator.isValidInet6Address("0:0:0:0:0:0:0::"), "IPV6 0:0:0:0:0:0:0:: should be valid");
+        assertTrue(validator.isValidInet6Address("0:0:0:0:0:0::"), "IPV6 0:0:0:0:0:0:: should be valid");
+        assertTrue(validator.isValidInet6Address("0:0:0:0:0::"), "IPV6 0:0:0:0:0:: should be valid");
+        assertTrue(validator.isValidInet6Address("0:0:0:0::"), "IPV6 0:0:0:0:: should be valid");
+        assertTrue(validator.isValidInet6Address("0:0:0::"), "IPV6 0:0:0:: should be valid");
+        assertTrue(validator.isValidInet6Address("0:0::"), "IPV6 0:0:: should be valid");
+        assertTrue(validator.isValidInet6Address("0::"), "IPV6 0:: should be valid");
+        // Invalid data
+        assertFalse(validator.isValidInet6Address("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX"), "IPV6 XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX should be invalid");
+        // Too many components
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:9999"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:8888:9999 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888::"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:8888:: should be invalid");
+        assertFalse(validator.isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888:9999"),
+                "IPV6 ::2222:3333:4444:5555:6666:7777:8888:9999 should be invalid");
+        // Too few components
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777"), "IPV6 1111:2222:3333:4444:5555:6666:7777 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666"), "IPV6 1111:2222:3333:4444:5555:6666 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555"), "IPV6 1111:2222:3333:4444:5555 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444"), "IPV6 1111:2222:3333:4444 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333"), "IPV6 1111:2222:3333 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222"), "IPV6 1111:2222 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111"), "IPV6 1111 should be invalid");
+        // Missing :
+        assertFalse(validator.isValidInet6Address("11112222:3333:4444:5555:6666:7777:8888"), "IPV6 11112222:3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:22223333:4444:5555:6666:7777:8888"), "IPV6 1111:22223333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:33334444:5555:6666:7777:8888"), "IPV6 1111:2222:33334444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:44445555:6666:7777:8888"), "IPV6 1111:2222:3333:44445555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:55556666:7777:8888"), "IPV6 1111:2222:3333:4444:55556666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:66667777:8888"), "IPV6 1111:2222:3333:4444:5555:66667777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:77778888"), "IPV6 1111:2222:3333:4444:5555:6666:77778888 should be invalid");
+        // Missing : intended for ::
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:"), "IPV6 1111:2222:3333:4444:5555:6666:7777: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:"), "IPV6 1111:2222:3333:4444:5555:6666: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:"), "IPV6 1111:2222:3333:4444:5555: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:"), "IPV6 1111:2222:3333:4444: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:"), "IPV6 1111:2222:3333: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:"), "IPV6 1111:2222: should be invalid");
+        assertFalse(validator.isValidInet6Address(":8888"), "IPV6 :8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":7777:8888"), "IPV6 :7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":6666:7777:8888"), "IPV6 :6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":5555:6666:7777:8888"), "IPV6 :5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":4444:5555:6666:7777:8888"), "IPV6 :4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":3333:4444:5555:6666:7777:8888"), "IPV6 :3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":2222:3333:4444:5555:6666:7777:8888"), "IPV6 :2222:3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666:7777:8888"),
+                "IPV6 :1111:2222:3333:4444:5555:6666:7777:8888 should be invalid");
+        // :::
+        assertFalse(validator.isValidInet6Address(":::2222:3333:4444:5555:6666:7777:8888"), "IPV6 :::2222:3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:::3333:4444:5555:6666:7777:8888"), "IPV6 1111:::3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:::4444:5555:6666:7777:8888"), "IPV6 1111:2222:::4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:::5555:6666:7777:8888"), "IPV6 1111:2222:3333:::5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:::6666:7777:8888"), "IPV6 1111:2222:3333:4444:::6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:::7777:8888"), "IPV6 1111:2222:3333:4444:5555:::7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:::8888"), "IPV6 1111:2222:3333:4444:5555:6666:::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:::"), "IPV6 1111:2222:3333:4444:5555:6666:7777::: should be invalid");
+        // Double ::
+        assertFalse(validator.isValidInet6Address("::2222::4444:5555:6666:7777:8888"), "IPV6 ::2222::4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("::2222:3333::5555:6666:7777:8888"), "IPV6 ::2222:3333::5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("::2222:3333:4444::6666:7777:8888"), "IPV6 ::2222:3333:4444::6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("::2222:3333:4444:5555::7777:8888"), "IPV6 ::2222:3333:4444:5555::7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("::2222:3333:4444:5555:7777::8888"), "IPV6 ::2222:3333:4444:5555:7777::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("::2222:3333:4444:5555:7777:8888::"), "IPV6 ::2222:3333:4444:5555:7777:8888:: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::3333::5555:6666:7777:8888"), "IPV6 1111::3333::5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::3333:4444::6666:7777:8888"), "IPV6 1111::3333:4444::6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::3333:4444:5555::7777:8888"), "IPV6 1111::3333:4444:5555::7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::3333:4444:5555:6666::8888"), "IPV6 1111::3333:4444:5555:6666::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::3333:4444:5555:6666:7777::"), "IPV6 1111::3333:4444:5555:6666:7777:: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::4444::6666:7777:8888"), "IPV6 1111:2222::4444::6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::4444:5555::7777:8888"), "IPV6 1111:2222::4444:5555::7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::4444:5555:6666::8888"), "IPV6 1111:2222::4444:5555:6666::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::4444:5555:6666:7777::"), "IPV6 1111:2222::4444:5555:6666:7777:: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333::5555::7777:8888"), "IPV6 1111:2222:3333::5555::7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333::5555:6666::8888"), "IPV6 1111:2222:3333::5555:6666::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333::5555:6666:7777::"), "IPV6 1111:2222:3333::5555:6666:7777:: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444::6666::8888"), "IPV6 1111:2222:3333:4444::6666::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444::6666:7777::"), "IPV6 1111:2222:3333:4444::6666:7777:: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555::7777::"), "IPV6 1111:2222:3333:4444:5555::7777:: should be invalid");
+        // Too many components"
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:1.2.3.4"),
+                "IPV6 1111:2222:3333:4444:5555:6666:7777:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666::1.2.3.4"), "IPV6 1111:2222:3333:4444:5555:6666::1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::2222:3333:4444:5555:6666:7777:1.2.3.4"), "IPV6 ::2222:3333:4444:5555:6666:7777:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:1.2.3.4.5"), "IPV6 1111:2222:3333:4444:5555:6666:1.2.3.4.5 should be invalid");
+        // Too few components
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:1.2.3.4"), "IPV6 1111:2222:3333:4444:5555:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:1.2.3.4"), "IPV6 1111:2222:3333:4444:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:1.2.3.4"), "IPV6 1111:2222:3333:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:1.2.3.4"), "IPV6 1111:2222:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:1.2.3.4"), "IPV6 1111:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1.2.3.4"), "IPV6 1.2.3.4 should be invalid");
+        // Missing :
+        assertFalse(validator.isValidInet6Address("11112222:3333:4444:5555:6666:1.2.3.4"), "IPV6 11112222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:22223333:4444:5555:6666:1.2.3.4"), "IPV6 1111:22223333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:33334444:5555:6666:1.2.3.4"), "IPV6 1111:2222:33334444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:44445555:6666:1.2.3.4"), "IPV6 1111:2222:3333:44445555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:55556666:1.2.3.4"), "IPV6 1111:2222:3333:4444:55556666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:66661.2.3.4"), "IPV6 1111:2222:3333:4444:5555:66661.2.3.4 should be invalid");
+        // Missing .
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:255255.255.255"),
+                "IPV6 1111:2222:3333:4444:5555:6666:255255.255.255 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:255.255255.255"),
+                "IPV6 1111:2222:3333:4444:5555:6666:255.255255.255 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:255.255.255255"),
+                "IPV6 1111:2222:3333:4444:5555:6666:255.255.255255 should be invalid");
+        // Missing : intended for ::
+        assertFalse(validator.isValidInet6Address(":1.2.3.4"), "IPV6 :1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":6666:1.2.3.4"), "IPV6 :6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":5555:6666:1.2.3.4"), "IPV6 :5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":4444:5555:6666:1.2.3.4"), "IPV6 :4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":3333:4444:5555:6666:1.2.3.4"), "IPV6 :3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":2222:3333:4444:5555:6666:1.2.3.4"), "IPV6 :2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666:1.2.3.4"), "IPV6 :1111:2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+        // :::
+        assertFalse(validator.isValidInet6Address(":::2222:3333:4444:5555:6666:1.2.3.4"), "IPV6 :::2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:::3333:4444:5555:6666:1.2.3.4"), "IPV6 1111:::3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:::4444:5555:6666:1.2.3.4"), "IPV6 1111:2222:::4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:::5555:6666:1.2.3.4"), "IPV6 1111:2222:3333:::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:::6666:1.2.3.4"), "IPV6 1111:2222:3333:4444:::6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:::1.2.3.4"), "IPV6 1111:2222:3333:4444:5555:::1.2.3.4 should be invalid");
+        // Double ::
+        assertFalse(validator.isValidInet6Address("::2222::4444:5555:6666:1.2.3.4"), "IPV6 ::2222::4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::2222:3333::5555:6666:1.2.3.4"), "IPV6 ::2222:3333::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::2222:3333:4444::6666:1.2.3.4"), "IPV6 ::2222:3333:4444::6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::2222:3333:4444:5555::1.2.3.4"), "IPV6 ::2222:3333:4444:5555::1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::3333::5555:6666:1.2.3.4"), "IPV6 1111::3333::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::3333:4444::6666:1.2.3.4"), "IPV6 1111::3333:4444::6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::3333:4444:5555::1.2.3.4"), "IPV6 1111::3333:4444:5555::1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::4444::6666:1.2.3.4"), "IPV6 1111:2222::4444::6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::4444:5555::1.2.3.4"), "IPV6 1111:2222::4444:5555::1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333::5555::1.2.3.4"), "IPV6 1111:2222:3333::5555::1.2.3.4 should be invalid");
+        // Missing parts
+        assertFalse(validator.isValidInet6Address("::."), "IPV6 ::. should be invalid");
+        assertFalse(validator.isValidInet6Address("::.."), "IPV6 ::.. should be invalid");
+        assertFalse(validator.isValidInet6Address("::..."), "IPV6 ::... should be invalid");
+        assertFalse(validator.isValidInet6Address("::1..."), "IPV6 ::1... should be invalid");
+        assertFalse(validator.isValidInet6Address("::1.2.."), "IPV6 ::1.2.. should be invalid");
+        assertFalse(validator.isValidInet6Address("::1.2.3."), "IPV6 ::1.2.3. should be invalid");
+        assertFalse(validator.isValidInet6Address("::.2.."), "IPV6 ::.2.. should be invalid");
+        assertFalse(validator.isValidInet6Address("::.2.3."), "IPV6 ::.2.3. should be invalid");
+        assertFalse(validator.isValidInet6Address("::.2.3.4"), "IPV6 ::.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::..3."), "IPV6 ::..3. should be invalid");
+        assertFalse(validator.isValidInet6Address("::..3.4"), "IPV6 ::..3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address("::...4"), "IPV6 ::...4 should be invalid");
+        // Extra : in front
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666:7777::"), "IPV6 :1111:2222:3333:4444:5555:6666:7777:: should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666::"), "IPV6 :1111:2222:3333:4444:5555:6666:: should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444:5555::"), "IPV6 :1111:2222:3333:4444:5555:: should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444::"), "IPV6 :1111:2222:3333:4444:: should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333::"), "IPV6 :1111:2222:3333:: should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222::"), "IPV6 :1111:2222:: should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::"), "IPV6 :1111:: should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666::8888"), "IPV6 :1111:2222:3333:4444:5555:6666::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444:5555::8888"), "IPV6 :1111:2222:3333:4444:5555::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444::8888"), "IPV6 :1111:2222:3333:4444::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333::8888"), "IPV6 :1111:2222:3333::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222::8888"), "IPV6 :1111:2222::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::8888"), "IPV6 :1111::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::8888"), "IPV6 :::8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444:5555::7777:8888"), "IPV6 :1111:2222:3333:4444:5555::7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444::7777:8888"), "IPV6 :1111:2222:3333:4444::7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333::7777:8888"), "IPV6 :1111:2222:3333::7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222::7777:8888"), "IPV6 :1111:2222::7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::7777:8888"), "IPV6 :1111::7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::7777:8888"), "IPV6 :::7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444::6666:7777:8888"), "IPV6 :1111:2222:3333:4444::6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333::6666:7777:8888"), "IPV6 :1111:2222:3333::6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222::6666:7777:8888"), "IPV6 :1111:2222::6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::6666:7777:8888"), "IPV6 :1111::6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::6666:7777:8888"), "IPV6 :::6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333::5555:6666:7777:8888"), "IPV6 :1111:2222:3333::5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222::5555:6666:7777:8888"), "IPV6 :1111:2222::5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::5555:6666:7777:8888"), "IPV6 :1111::5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::5555:6666:7777:8888"), "IPV6 :::5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222::4444:5555:6666:7777:8888"), "IPV6 :1111:2222::4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::4444:5555:6666:7777:8888"), "IPV6 :1111::4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::4444:5555:6666:7777:8888"), "IPV6 :::4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::3333:4444:5555:6666:7777:8888"), "IPV6 :1111::3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::3333:4444:5555:6666:7777:8888"), "IPV6 :::3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::2222:3333:4444:5555:6666:7777:8888"), "IPV6 :::2222:3333:4444:5555:6666:7777:8888 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666:1.2.3.4"), "IPV6 :1111:2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444:5555::1.2.3.4"), "IPV6 :1111:2222:3333:4444:5555::1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444::1.2.3.4"), "IPV6 :1111:2222:3333:4444::1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333::1.2.3.4"), "IPV6 :1111:2222:3333::1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222::1.2.3.4"), "IPV6 :1111:2222::1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::1.2.3.4"), "IPV6 :1111::1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::1.2.3.4"), "IPV6 :::1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333:4444::6666:1.2.3.4"), "IPV6 :1111:2222:3333:4444::6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333::6666:1.2.3.4"), "IPV6 :1111:2222:3333::6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222::6666:1.2.3.4"), "IPV6 :1111:2222::6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::6666:1.2.3.4"), "IPV6 :1111::6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::6666:1.2.3.4"), "IPV6 :::6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222:3333::5555:6666:1.2.3.4"), "IPV6 :1111:2222:3333::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222::5555:6666:1.2.3.4"), "IPV6 :1111:2222::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::5555:6666:1.2.3.4"), "IPV6 :1111::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::5555:6666:1.2.3.4"), "IPV6 :::5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111:2222::4444:5555:6666:1.2.3.4"), "IPV6 :1111:2222::4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::4444:5555:6666:1.2.3.4"), "IPV6 :1111::4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::4444:5555:6666:1.2.3.4"), "IPV6 :::4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":1111::3333:4444:5555:6666:1.2.3.4"), "IPV6 :1111::3333:4444:5555:6666:1.2.3.4 should be invalid");
+        assertFalse(validator.isValidInet6Address(":::2222:3333:4444:5555:6666:1.2.3.4"), "IPV6 :::2222:3333:4444:5555:6666:1.2.3.4 should be invalid");
+        // Extra : at end
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:::"), "IPV6 1111:2222:3333:4444:5555:6666:7777::: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:::"), "IPV6 1111:2222:3333:4444:5555:6666::: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:::"), "IPV6 1111:2222:3333:4444:5555::: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:::"), "IPV6 1111:2222:3333:4444::: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:::"), "IPV6 1111:2222:3333::: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:::"), "IPV6 1111:2222::: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:::"), "IPV6 1111::: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555:6666::8888:"), "IPV6 1111:2222:3333:4444:5555:6666::8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555::8888:"), "IPV6 1111:2222:3333:4444:5555::8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444::8888:"), "IPV6 1111:2222:3333:4444::8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333::8888:"), "IPV6 1111:2222:3333::8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::8888:"), "IPV6 1111:2222::8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::8888:"), "IPV6 1111::8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("::8888:"), "IPV6 ::8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444:5555::7777:8888:"), "IPV6 1111:2222:3333:4444:5555::7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444::7777:8888:"), "IPV6 1111:2222:3333:4444::7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333::7777:8888:"), "IPV6 1111:2222:3333::7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::7777:8888:"), "IPV6 1111:2222::7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::7777:8888:"), "IPV6 1111::7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("::7777:8888:"), "IPV6 ::7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333:4444::6666:7777:8888:"), "IPV6 1111:2222:3333:4444::6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333::6666:7777:8888:"), "IPV6 1111:2222:3333::6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::6666:7777:8888:"), "IPV6 1111:2222::6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::6666:7777:8888:"), "IPV6 1111::6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("::6666:7777:8888:"), "IPV6 ::6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222:3333::5555:6666:7777:8888:"), "IPV6 1111:2222:3333::5555:6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::5555:6666:7777:8888:"), "IPV6 1111:2222::5555:6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::5555:6666:7777:8888:"), "IPV6 1111::5555:6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("::5555:6666:7777:8888:"), "IPV6 ::5555:6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111:2222::4444:5555:6666:7777:8888:"), "IPV6 1111:2222::4444:5555:6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::4444:5555:6666:7777:8888:"), "IPV6 1111::4444:5555:6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("::4444:5555:6666:7777:8888:"), "IPV6 ::4444:5555:6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("1111::3333:4444:5555:6666:7777:8888:"), "IPV6 1111::3333:4444:5555:6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("::3333:4444:5555:6666:7777:8888:"), "IPV6 ::3333:4444:5555:6666:7777:8888: should be invalid");
+        assertFalse(validator.isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888:"), "IPV6 ::2222:3333:4444:5555:6666:7777:8888: should be invalid");
+        assertTrue(validator.isValidInet6Address("0:a:b:c:d:e:f::"), "IPV6 0:a:b:c:d:e:f:: should be valid");
+        assertTrue(validator.isValidInet6Address("::0:a:b:c:d:e:f"), "IPV6 ::0:a:b:c:d:e:f should be valid"); // syntactically correct, but bad form (::0:...
+                                                                                                              // could be combined)
+        assertTrue(validator.isValidInet6Address("a:b:c:d:e:f:0::"), "IPV6 a:b:c:d:e:f:0:: should be valid");
+        assertFalse(validator.isValidInet6Address("':10.0.0.1"), "IPV6 ':10.0.0.1 should be invalid");
     }
 
     /**
      * Test reserved IPs.
      */
+    @Test
     public void testReservedInetAddresses() {
-        assertTrue("localhost IP should be valid",            validator.isValid("127.0.0.1"));
-        assertTrue("broadcast IP should be valid",            validator.isValid("255.255.255.255"));
+        assertTrue(validator.isValid("127.0.0.1"), "localhost IP should be valid");
+        assertTrue(validator.isValid("255.255.255.255"), "broadcast IP should be valid");
+    }
+
+    @Test
+    public void testVALIDATOR_335() {
+        assertTrue(validator.isValid("2001:0438:FFFE:0000:0000:0000:0000:0A35"), "2001:0438:FFFE:0000:0000:0000:0000:0A35 should be valid");
+    }
+
+    @Test
+    public void testVALIDATOR_419() {
+        String addr;
+        addr = "0:0:0:0:0:0:13.1.68.3";
+        assertTrue(validator.isValid(addr));
+        addr = "0:0:0:0:0:FFFF:129.144.52.38";
+        assertTrue(validator.isValid(addr), addr);
+        addr = "::13.1.68.3";
+        assertTrue(validator.isValid(addr), addr);
+        addr = "::FFFF:129.144.52.38";
+        assertTrue(validator.isValid(addr), addr);
+
+        addr = "::ffff:192.168.1.1:192.168.1.1";
+        assertFalse(validator.isValid(addr), addr);
+        addr = "::192.168.1.1:192.168.1.1";
+        assertFalse(validator.isValid(addr), addr);
     }
 
     /**
-     * Test obviously broken IPs.
+     * Inet6Address may also contain a scope id
      */
-    public void testBrokenInetAddresses() {
-        assertFalse("IP with characters should be invalid",     validator.isValid("124.14.32.abc"));
-        // TODO: there is some debate as to whether leading zeros should be allowed
-        // They are ambiguous: does the leading 0 mean octal?
-        assertFalse("IP with leading zeroes should be invalid", validator.isValid("124.14.32.01"));
-        assertFalse("IP with three groups should be invalid",   validator.isValid("23.64.12"));
-        assertFalse("IP with five groups should be invalid",    validator.isValid("26.34.23.77.234"));
-        assertFalse("IP empty string should be invalid", validator.isValidInet6Address(""));// empty string
-    }
-
-    /**
-     * Test IPv6 addresses.
-     * <p>These tests were ported from a
-     * <a href="http://download.dartware.com/thirdparty/test-ipv6-regex.pl">Perl script</a>.</p>
-     *
-     */
-    public void testIPv6() {
-        // The original Perl script contained a lot of duplicate tests.
-        // I removed the duplicates I noticed, but there may be more.
-        assertFalse("IPV6 empty string should be invalid", validator.isValidInet6Address(""));// empty string
-        assertTrue("IPV6 ::1 should be valid", validator.isValidInet6Address("::1"));// loopback, compressed, non-routable
-        assertTrue("IPV6 :: should be valid", validator.isValidInet6Address("::"));// unspecified, compressed, non-routable
-        assertTrue("IPV6 0:0:0:0:0:0:0:1 should be valid", validator.isValidInet6Address("0:0:0:0:0:0:0:1"));// loopback, full
-        assertTrue("IPV6 0:0:0:0:0:0:0:0 should be valid", validator.isValidInet6Address("0:0:0:0:0:0:0:0"));// unspecified, full
-        assertTrue("IPV6 2001:DB8:0:0:8:800:200C:417A should be valid", validator.isValidInet6Address("2001:DB8:0:0:8:800:200C:417A"));// unicast, full
-        assertTrue("IPV6 FF01:0:0:0:0:0:0:101 should be valid", validator.isValidInet6Address("FF01:0:0:0:0:0:0:101"));// multicast, full
-        assertTrue("IPV6 2001:DB8::8:800:200C:417A should be valid", validator.isValidInet6Address("2001:DB8::8:800:200C:417A"));// unicast, compressed
-        assertTrue("IPV6 FF01::101 should be valid", validator.isValidInet6Address("FF01::101"));// multicast, compressed
-        assertFalse("IPV6 2001:DB8:0:0:8:800:200C:417A:221 should be invalid", validator.isValidInet6Address("2001:DB8:0:0:8:800:200C:417A:221"));// unicast, full
-        assertFalse("IPV6 FF01::101::2 should be invalid", validator.isValidInet6Address("FF01::101::2"));// multicast, compressed
-        assertTrue("IPV6 fe80::217:f2ff:fe07:ed62 should be valid", validator.isValidInet6Address("fe80::217:f2ff:fe07:ed62"));
-        assertTrue("IPV6 2001:0000:1234:0000:0000:C1C0:ABCD:0876 should be valid", validator.isValidInet6Address("2001:0000:1234:0000:0000:C1C0:ABCD:0876"));
-        assertTrue("IPV6 3ffe:0b00:0000:0000:0001:0000:0000:000a should be valid", validator.isValidInet6Address("3ffe:0b00:0000:0000:0001:0000:0000:000a"));
-        assertTrue("IPV6 FF02:0000:0000:0000:0000:0000:0000:0001 should be valid", validator.isValidInet6Address("FF02:0000:0000:0000:0000:0000:0000:0001"));
-        assertTrue("IPV6 0000:0000:0000:0000:0000:0000:0000:0001 should be valid", validator.isValidInet6Address("0000:0000:0000:0000:0000:0000:0000:0001"));
-        assertTrue("IPV6 0000:0000:0000:0000:0000:0000:0000:0000 should be valid", validator.isValidInet6Address("0000:0000:0000:0000:0000:0000:0000:0000"));
-        assertFalse("IPV6 02001:0000:1234:0000:0000:C1C0:ABCD:0876 should be invalid", validator.isValidInet6Address("02001:0000:1234:0000:0000:C1C0:ABCD:0876")); // extra 0 not allowed!
-        assertFalse("IPV6 2001:0000:1234:0000:00001:C1C0:ABCD:0876 should be invalid", validator.isValidInet6Address("2001:0000:1234:0000:00001:C1C0:ABCD:0876")); // extra 0 not allowed!
-        assertFalse("IPV6 2001:0000:1234:0000:0000:C1C0:ABCD:0876 0 should be invalid", validator.isValidInet6Address("2001:0000:1234:0000:0000:C1C0:ABCD:0876 0")); // junk after valid address
-        assertFalse("IPV6 2001:0000:1234: 0000:0000:C1C0:ABCD:0876 should be invalid", validator.isValidInet6Address("2001:0000:1234: 0000:0000:C1C0:ABCD:0876")); // internal space
-        assertFalse("IPV6 3ffe:0b00:0000:0001:0000:0000:000a should be invalid", validator.isValidInet6Address("3ffe:0b00:0000:0001:0000:0000:000a")); // seven segments
-        assertFalse("IPV6 FF02:0000:0000:0000:0000:0000:0000:0000:0001 should be invalid", validator.isValidInet6Address("FF02:0000:0000:0000:0000:0000:0000:0000:0001")); // nine segments
-        assertFalse("IPV6 3ffe:b00::1::a should be invalid", validator.isValidInet6Address("3ffe:b00::1::a")); // double "::"
-        assertFalse("IPV6 ::1111:2222:3333:4444:5555:6666:: should be invalid", validator.isValidInet6Address("::1111:2222:3333:4444:5555:6666::")); // double "::"
-        assertTrue("IPV6 2::10 should be valid", validator.isValidInet6Address("2::10"));
-        assertTrue("IPV6 ff02::1 should be valid", validator.isValidInet6Address("ff02::1"));
-        assertTrue("IPV6 fe80:: should be valid", validator.isValidInet6Address("fe80::"));
-        assertTrue("IPV6 2002:: should be valid", validator.isValidInet6Address("2002::"));
-        assertTrue("IPV6 2001:db8:: should be valid", validator.isValidInet6Address("2001:db8::"));
-        assertTrue("IPV6 2001:0db8:1234:: should be valid", validator.isValidInet6Address("2001:0db8:1234::"));
-        assertTrue("IPV6 ::ffff:0:0 should be valid", validator.isValidInet6Address("::ffff:0:0"));
-        assertTrue("IPV6 1:2:3:4:5:6:7:8 should be valid", validator.isValidInet6Address("1:2:3:4:5:6:7:8"));
-        assertTrue("IPV6 1:2:3:4:5:6::8 should be valid", validator.isValidInet6Address("1:2:3:4:5:6::8"));
-        assertTrue("IPV6 1:2:3:4:5::8 should be valid", validator.isValidInet6Address("1:2:3:4:5::8"));
-        assertTrue("IPV6 1:2:3:4::8 should be valid", validator.isValidInet6Address("1:2:3:4::8"));
-        assertTrue("IPV6 1:2:3::8 should be valid", validator.isValidInet6Address("1:2:3::8"));
-        assertTrue("IPV6 1:2::8 should be valid", validator.isValidInet6Address("1:2::8"));
-        assertTrue("IPV6 1::8 should be valid", validator.isValidInet6Address("1::8"));
-        assertTrue("IPV6 1::2:3:4:5:6:7 should be valid", validator.isValidInet6Address("1::2:3:4:5:6:7"));
-        assertTrue("IPV6 1::2:3:4:5:6 should be valid", validator.isValidInet6Address("1::2:3:4:5:6"));
-        assertTrue("IPV6 1::2:3:4:5 should be valid", validator.isValidInet6Address("1::2:3:4:5"));
-        assertTrue("IPV6 1::2:3:4 should be valid", validator.isValidInet6Address("1::2:3:4"));
-        assertTrue("IPV6 1::2:3 should be valid", validator.isValidInet6Address("1::2:3"));
-        assertTrue("IPV6 ::2:3:4:5:6:7:8 should be valid", validator.isValidInet6Address("::2:3:4:5:6:7:8"));
-        assertTrue("IPV6 ::2:3:4:5:6:7 should be valid", validator.isValidInet6Address("::2:3:4:5:6:7"));
-        assertTrue("IPV6 ::2:3:4:5:6 should be valid", validator.isValidInet6Address("::2:3:4:5:6"));
-        assertTrue("IPV6 ::2:3:4:5 should be valid", validator.isValidInet6Address("::2:3:4:5"));
-        assertTrue("IPV6 ::2:3:4 should be valid", validator.isValidInet6Address("::2:3:4"));
-        assertTrue("IPV6 ::2:3 should be valid", validator.isValidInet6Address("::2:3"));
-        assertTrue("IPV6 ::8 should be valid", validator.isValidInet6Address("::8"));
-        assertTrue("IPV6 1:2:3:4:5:6:: should be valid", validator.isValidInet6Address("1:2:3:4:5:6::"));
-        assertTrue("IPV6 1:2:3:4:5:: should be valid", validator.isValidInet6Address("1:2:3:4:5::"));
-        assertTrue("IPV6 1:2:3:4:: should be valid", validator.isValidInet6Address("1:2:3:4::"));
-        assertTrue("IPV6 1:2:3:: should be valid", validator.isValidInet6Address("1:2:3::"));
-        assertTrue("IPV6 1:2:: should be valid", validator.isValidInet6Address("1:2::"));
-        assertTrue("IPV6 1:: should be valid", validator.isValidInet6Address("1::"));
-        assertTrue("IPV6 1:2:3:4:5::7:8 should be valid", validator.isValidInet6Address("1:2:3:4:5::7:8"));
-        assertFalse("IPV6 1:2:3::4:5::7:8 should be invalid", validator.isValidInet6Address("1:2:3::4:5::7:8")); // Double "::"
-        assertFalse("IPV6 12345::6:7:8 should be invalid", validator.isValidInet6Address("12345::6:7:8"));
-        assertTrue("IPV6 1:2:3:4::7:8 should be valid", validator.isValidInet6Address("1:2:3:4::7:8"));
-        assertTrue("IPV6 1:2:3::7:8 should be valid", validator.isValidInet6Address("1:2:3::7:8"));
-        assertTrue("IPV6 1:2::7:8 should be valid", validator.isValidInet6Address("1:2::7:8"));
-        assertTrue("IPV6 1::7:8 should be valid", validator.isValidInet6Address("1::7:8"));
-        // IPv4 addresses as dotted-quads
-        assertTrue("IPV6 1:2:3:4:5:6:1.2.3.4 should be valid", validator.isValidInet6Address("1:2:3:4:5:6:1.2.3.4"));
-        assertTrue("IPV6 1:2:3:4:5::1.2.3.4 should be valid", validator.isValidInet6Address("1:2:3:4:5::1.2.3.4"));
-        assertTrue("IPV6 1:2:3:4::1.2.3.4 should be valid", validator.isValidInet6Address("1:2:3:4::1.2.3.4"));
-        assertTrue("IPV6 1:2:3::1.2.3.4 should be valid", validator.isValidInet6Address("1:2:3::1.2.3.4"));
-        assertTrue("IPV6 1:2::1.2.3.4 should be valid", validator.isValidInet6Address("1:2::1.2.3.4"));
-        assertTrue("IPV6 1::1.2.3.4 should be valid", validator.isValidInet6Address("1::1.2.3.4"));
-        assertTrue("IPV6 1:2:3:4::5:1.2.3.4 should be valid", validator.isValidInet6Address("1:2:3:4::5:1.2.3.4"));
-        assertTrue("IPV6 1:2:3::5:1.2.3.4 should be valid", validator.isValidInet6Address("1:2:3::5:1.2.3.4"));
-        assertTrue("IPV6 1:2::5:1.2.3.4 should be valid", validator.isValidInet6Address("1:2::5:1.2.3.4"));
-        assertTrue("IPV6 1::5:1.2.3.4 should be valid", validator.isValidInet6Address("1::5:1.2.3.4"));
-        assertTrue("IPV6 1::5:11.22.33.44 should be valid", validator.isValidInet6Address("1::5:11.22.33.44"));
-        assertFalse("IPV6 1::5:400.2.3.4 should be invalid", validator.isValidInet6Address("1::5:400.2.3.4"));
-        assertFalse("IPV6 1::5:260.2.3.4 should be invalid", validator.isValidInet6Address("1::5:260.2.3.4"));
-        assertFalse("IPV6 1::5:256.2.3.4 should be invalid", validator.isValidInet6Address("1::5:256.2.3.4"));
-        assertFalse("IPV6 1::5:1.256.3.4 should be invalid", validator.isValidInet6Address("1::5:1.256.3.4"));
-        assertFalse("IPV6 1::5:1.2.256.4 should be invalid", validator.isValidInet6Address("1::5:1.2.256.4"));
-        assertFalse("IPV6 1::5:1.2.3.256 should be invalid", validator.isValidInet6Address("1::5:1.2.3.256"));
-        assertFalse("IPV6 1::5:300.2.3.4 should be invalid", validator.isValidInet6Address("1::5:300.2.3.4"));
-        assertFalse("IPV6 1::5:1.300.3.4 should be invalid", validator.isValidInet6Address("1::5:1.300.3.4"));
-        assertFalse("IPV6 1::5:1.2.300.4 should be invalid", validator.isValidInet6Address("1::5:1.2.300.4"));
-        assertFalse("IPV6 1::5:1.2.3.300 should be invalid", validator.isValidInet6Address("1::5:1.2.3.300"));
-        assertFalse("IPV6 1::5:900.2.3.4 should be invalid", validator.isValidInet6Address("1::5:900.2.3.4"));
-        assertFalse("IPV6 1::5:1.900.3.4 should be invalid", validator.isValidInet6Address("1::5:1.900.3.4"));
-        assertFalse("IPV6 1::5:1.2.900.4 should be invalid", validator.isValidInet6Address("1::5:1.2.900.4"));
-        assertFalse("IPV6 1::5:1.2.3.900 should be invalid", validator.isValidInet6Address("1::5:1.2.3.900"));
-        assertFalse("IPV6 1::5:300.300.300.300 should be invalid", validator.isValidInet6Address("1::5:300.300.300.300"));
-        assertFalse("IPV6 1::5:3000.30.30.30 should be invalid", validator.isValidInet6Address("1::5:3000.30.30.30"));
-        assertFalse("IPV6 1::400.2.3.4 should be invalid", validator.isValidInet6Address("1::400.2.3.4"));
-        assertFalse("IPV6 1::260.2.3.4 should be invalid", validator.isValidInet6Address("1::260.2.3.4"));
-        assertFalse("IPV6 1::256.2.3.4 should be invalid", validator.isValidInet6Address("1::256.2.3.4"));
-        assertFalse("IPV6 1::1.256.3.4 should be invalid", validator.isValidInet6Address("1::1.256.3.4"));
-        assertFalse("IPV6 1::1.2.256.4 should be invalid", validator.isValidInet6Address("1::1.2.256.4"));
-        assertFalse("IPV6 1::1.2.3.256 should be invalid", validator.isValidInet6Address("1::1.2.3.256"));
-        assertFalse("IPV6 1::300.2.3.4 should be invalid", validator.isValidInet6Address("1::300.2.3.4"));
-        assertFalse("IPV6 1::1.300.3.4 should be invalid", validator.isValidInet6Address("1::1.300.3.4"));
-        assertFalse("IPV6 1::1.2.300.4 should be invalid", validator.isValidInet6Address("1::1.2.300.4"));
-        assertFalse("IPV6 1::1.2.3.300 should be invalid", validator.isValidInet6Address("1::1.2.3.300"));
-        assertFalse("IPV6 1::900.2.3.4 should be invalid", validator.isValidInet6Address("1::900.2.3.4"));
-        assertFalse("IPV6 1::1.900.3.4 should be invalid", validator.isValidInet6Address("1::1.900.3.4"));
-        assertFalse("IPV6 1::1.2.900.4 should be invalid", validator.isValidInet6Address("1::1.2.900.4"));
-        assertFalse("IPV6 1::1.2.3.900 should be invalid", validator.isValidInet6Address("1::1.2.3.900"));
-        assertFalse("IPV6 1::300.300.300.300 should be invalid", validator.isValidInet6Address("1::300.300.300.300"));
-        assertFalse("IPV6 1::3000.30.30.30 should be invalid", validator.isValidInet6Address("1::3000.30.30.30"));
-        assertFalse("IPV6 ::400.2.3.4 should be invalid", validator.isValidInet6Address("::400.2.3.4"));
-        assertFalse("IPV6 ::260.2.3.4 should be invalid", validator.isValidInet6Address("::260.2.3.4"));
-        assertFalse("IPV6 ::256.2.3.4 should be invalid", validator.isValidInet6Address("::256.2.3.4"));
-        assertFalse("IPV6 ::1.256.3.4 should be invalid", validator.isValidInet6Address("::1.256.3.4"));
-        assertFalse("IPV6 ::1.2.256.4 should be invalid", validator.isValidInet6Address("::1.2.256.4"));
-        assertFalse("IPV6 ::1.2.3.256 should be invalid", validator.isValidInet6Address("::1.2.3.256"));
-        assertFalse("IPV6 ::300.2.3.4 should be invalid", validator.isValidInet6Address("::300.2.3.4"));
-        assertFalse("IPV6 ::1.300.3.4 should be invalid", validator.isValidInet6Address("::1.300.3.4"));
-        assertFalse("IPV6 ::1.2.300.4 should be invalid", validator.isValidInet6Address("::1.2.300.4"));
-        assertFalse("IPV6 ::1.2.3.300 should be invalid", validator.isValidInet6Address("::1.2.3.300"));
-        assertFalse("IPV6 ::900.2.3.4 should be invalid", validator.isValidInet6Address("::900.2.3.4"));
-        assertFalse("IPV6 ::1.900.3.4 should be invalid", validator.isValidInet6Address("::1.900.3.4"));
-        assertFalse("IPV6 ::1.2.900.4 should be invalid", validator.isValidInet6Address("::1.2.900.4"));
-        assertFalse("IPV6 ::1.2.3.900 should be invalid", validator.isValidInet6Address("::1.2.3.900"));
-        assertFalse("IPV6 ::300.300.300.300 should be invalid", validator.isValidInet6Address("::300.300.300.300"));
-        assertFalse("IPV6 ::3000.30.30.30 should be invalid", validator.isValidInet6Address("::3000.30.30.30"));
-        assertTrue("IPV6 fe80::217:f2ff:254.7.237.98 should be valid", validator.isValidInet6Address("fe80::217:f2ff:254.7.237.98"));
-        assertTrue("IPV6 ::ffff:192.168.1.26 should be valid", validator.isValidInet6Address("::ffff:192.168.1.26"));
-        assertFalse("IPV6 2001:1:1:1:1:1:255Z255X255Y255 should be invalid", validator.isValidInet6Address("2001:1:1:1:1:1:255Z255X255Y255")); // garbage instead of "." in IPv4
-        assertFalse("IPV6 ::ffff:192x168.1.26 should be invalid", validator.isValidInet6Address("::ffff:192x168.1.26")); // ditto
-        assertTrue("IPV6 ::ffff:192.168.1.1 should be valid", validator.isValidInet6Address("::ffff:192.168.1.1"));
-        assertTrue("IPV6 0:0:0:0:0:0:13.1.68.3 should be valid", validator.isValidInet6Address("0:0:0:0:0:0:13.1.68.3"));// IPv4-compatible IPv6 address, full, deprecated
-        assertTrue("IPV6 0:0:0:0:0:FFFF:129.144.52.38 should be valid", validator.isValidInet6Address("0:0:0:0:0:FFFF:129.144.52.38"));// IPv4-mapped IPv6 address, full
-        assertTrue("IPV6 ::13.1.68.3 should be valid", validator.isValidInet6Address("::13.1.68.3"));// IPv4-compatible IPv6 address, compressed, deprecated
-        assertTrue("IPV6 ::FFFF:129.144.52.38 should be valid", validator.isValidInet6Address("::FFFF:129.144.52.38"));// IPv4-mapped IPv6 address, compressed
-        assertTrue("IPV6 fe80:0:0:0:204:61ff:254.157.241.86 should be valid", validator.isValidInet6Address("fe80:0:0:0:204:61ff:254.157.241.86"));
-        assertTrue("IPV6 fe80::204:61ff:254.157.241.86 should be valid", validator.isValidInet6Address("fe80::204:61ff:254.157.241.86"));
-        assertTrue("IPV6 ::ffff:12.34.56.78 should be valid", validator.isValidInet6Address("::ffff:12.34.56.78"));
-        assertFalse("IPV6 ::ffff:2.3.4 should be invalid", validator.isValidInet6Address("::ffff:2.3.4"));
-        assertFalse("IPV6 ::ffff:257.1.2.3 should be invalid", validator.isValidInet6Address("::ffff:257.1.2.3"));
-        assertFalse("IPV6 1.2.3.4 should be invalid", validator.isValidInet6Address("1.2.3.4"));
-        assertFalse("IPV6 1.2.3.4:1111:2222:3333:4444::5555 should be invalid", validator.isValidInet6Address("1.2.3.4:1111:2222:3333:4444::5555"));
-        assertFalse("IPV6 1.2.3.4:1111:2222:3333::5555 should be invalid", validator.isValidInet6Address("1.2.3.4:1111:2222:3333::5555"));
-        assertFalse("IPV6 1.2.3.4:1111:2222::5555 should be invalid", validator.isValidInet6Address("1.2.3.4:1111:2222::5555"));
-        assertFalse("IPV6 1.2.3.4:1111::5555 should be invalid", validator.isValidInet6Address("1.2.3.4:1111::5555"));
-        assertFalse("IPV6 1.2.3.4::5555 should be invalid", validator.isValidInet6Address("1.2.3.4::5555"));
-        assertFalse("IPV6 1.2.3.4:: should be invalid", validator.isValidInet6Address("1.2.3.4::"));
-        // Testing IPv4 addresses represented as dotted-quads
-        // Leading zeroes in IPv4 addresses not allowed: some systems treat the leading "0" in ".086" as the start of an octal number
-        // Update: The BNF in RFC-3986 explicitly defines the dec-octet (for IPv4 addresses) not to have a leading zero
-        assertFalse("IPV6 fe80:0000:0000:0000:0204:61ff:254.157.241.086 should be invalid", validator.isValidInet6Address("fe80:0000:0000:0000:0204:61ff:254.157.241.086"));
-        assertTrue("IPV6 ::ffff:192.0.2.128 should be valid", validator.isValidInet6Address("::ffff:192.0.2.128")); // but this is OK, since there's a single digit
-        assertFalse("IPV6 XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4 should be invalid", validator.isValidInet6Address("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:00.00.00.00 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:00.00.00.00"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:000.000.000.000 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:000.000.000.000"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:256.256.256.256 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:256.256.256.256"));
-        assertTrue("IPV6 fe80:0000:0000:0000:0204:61ff:fe9d:f156 should be valid", validator.isValidInet6Address("fe80:0000:0000:0000:0204:61ff:fe9d:f156"));
-        assertTrue("IPV6 fe80:0:0:0:204:61ff:fe9d:f156 should be valid", validator.isValidInet6Address("fe80:0:0:0:204:61ff:fe9d:f156"));
-        assertTrue("IPV6 fe80::204:61ff:fe9d:f156 should be valid", validator.isValidInet6Address("fe80::204:61ff:fe9d:f156"));
-        assertFalse("IPV6 : should be invalid", validator.isValidInet6Address(":"));
-        assertTrue("IPV6 ::ffff:c000:280 should be valid", validator.isValidInet6Address("::ffff:c000:280"));
-        assertFalse("IPV6 1111:2222:3333:4444::5555: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444::5555:"));
-        assertFalse("IPV6 1111:2222:3333::5555: should be invalid", validator.isValidInet6Address("1111:2222:3333::5555:"));
-        assertFalse("IPV6 1111:2222::5555: should be invalid", validator.isValidInet6Address("1111:2222::5555:"));
-        assertFalse("IPV6 1111::5555: should be invalid", validator.isValidInet6Address("1111::5555:"));
-        assertFalse("IPV6 ::5555: should be invalid", validator.isValidInet6Address("::5555:"));
-        assertFalse("IPV6 ::: should be invalid", validator.isValidInet6Address(":::"));
-        assertFalse("IPV6 1111: should be invalid", validator.isValidInet6Address("1111:"));
-        assertFalse("IPV6 :1111:2222:3333:4444::5555 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444::5555"));
-        assertFalse("IPV6 :1111:2222:3333::5555 should be invalid", validator.isValidInet6Address(":1111:2222:3333::5555"));
-        assertFalse("IPV6 :1111:2222::5555 should be invalid", validator.isValidInet6Address(":1111:2222::5555"));
-        assertFalse("IPV6 :1111::5555 should be invalid", validator.isValidInet6Address(":1111::5555"));
-        assertFalse("IPV6 :::5555 should be invalid", validator.isValidInet6Address(":::5555"));
-        assertTrue("IPV6 2001:0db8:85a3:0000:0000:8a2e:0370:7334 should be valid", validator.isValidInet6Address("2001:0db8:85a3:0000:0000:8a2e:0370:7334"));
-        assertTrue("IPV6 2001:db8:85a3:0:0:8a2e:370:7334 should be valid", validator.isValidInet6Address("2001:db8:85a3:0:0:8a2e:370:7334"));
-        assertTrue("IPV6 2001:db8:85a3::8a2e:370:7334 should be valid", validator.isValidInet6Address("2001:db8:85a3::8a2e:370:7334"));
-        assertTrue("IPV6 2001:0db8:0000:0000:0000:0000:1428:57ab should be valid", validator.isValidInet6Address("2001:0db8:0000:0000:0000:0000:1428:57ab"));
-        assertTrue("IPV6 2001:0db8:0000:0000:0000::1428:57ab should be valid", validator.isValidInet6Address("2001:0db8:0000:0000:0000::1428:57ab"));
-        assertTrue("IPV6 2001:0db8:0:0:0:0:1428:57ab should be valid", validator.isValidInet6Address("2001:0db8:0:0:0:0:1428:57ab"));
-        assertTrue("IPV6 2001:0db8:0:0::1428:57ab should be valid", validator.isValidInet6Address("2001:0db8:0:0::1428:57ab"));
-        assertTrue("IPV6 2001:0db8::1428:57ab should be valid", validator.isValidInet6Address("2001:0db8::1428:57ab"));
-        assertTrue("IPV6 2001:db8::1428:57ab should be valid", validator.isValidInet6Address("2001:db8::1428:57ab"));
-        assertTrue("IPV6 ::ffff:0c22:384e should be valid", validator.isValidInet6Address("::ffff:0c22:384e"));
-        assertTrue("IPV6 2001:0db8:1234:0000:0000:0000:0000:0000 should be valid", validator.isValidInet6Address("2001:0db8:1234:0000:0000:0000:0000:0000"));
-        assertTrue("IPV6 2001:0db8:1234:ffff:ffff:ffff:ffff:ffff should be valid", validator.isValidInet6Address("2001:0db8:1234:ffff:ffff:ffff:ffff:ffff"));
-        assertTrue("IPV6 2001:db8:a::123 should be valid", validator.isValidInet6Address("2001:db8:a::123"));
-        assertFalse("IPV6 123 should be invalid", validator.isValidInet6Address("123"));
-        assertFalse("IPV6 ldkfj should be invalid", validator.isValidInet6Address("ldkfj"));
-        assertFalse("IPV6 2001::FFD3::57ab should be invalid", validator.isValidInet6Address("2001::FFD3::57ab"));
-        assertFalse("IPV6 2001:db8:85a3::8a2e:37023:7334 should be invalid", validator.isValidInet6Address("2001:db8:85a3::8a2e:37023:7334"));
-        assertFalse("IPV6 2001:db8:85a3::8a2e:370k:7334 should be invalid", validator.isValidInet6Address("2001:db8:85a3::8a2e:370k:7334"));
-        assertFalse("IPV6 1:2:3:4:5:6:7:8:9 should be invalid", validator.isValidInet6Address("1:2:3:4:5:6:7:8:9"));
-        assertFalse("IPV6 1::2::3 should be invalid", validator.isValidInet6Address("1::2::3"));
-        assertFalse("IPV6 1:::3:4:5 should be invalid", validator.isValidInet6Address("1:::3:4:5"));
-        assertFalse("IPV6 1:2:3::4:5:6:7:8:9 should be invalid", validator.isValidInet6Address("1:2:3::4:5:6:7:8:9"));
-        assertTrue("IPV6 1111:2222:3333:4444:5555:6666:7777:8888 should be valid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888"));
-        assertTrue("IPV6 1111:2222:3333:4444:5555:6666:7777:: should be valid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777::"));
-        assertTrue("IPV6 1111:2222:3333:4444:5555:6666:: should be valid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666::"));
-        assertTrue("IPV6 1111:2222:3333:4444:5555:: should be valid", validator.isValidInet6Address("1111:2222:3333:4444:5555::"));
-        assertTrue("IPV6 1111:2222:3333:4444:: should be valid", validator.isValidInet6Address("1111:2222:3333:4444::"));
-        assertTrue("IPV6 1111:2222:3333:: should be valid", validator.isValidInet6Address("1111:2222:3333::"));
-        assertTrue("IPV6 1111:2222:: should be valid", validator.isValidInet6Address("1111:2222::"));
-        assertTrue("IPV6 1111:: should be valid", validator.isValidInet6Address("1111::"));
-        assertTrue("IPV6 1111:2222:3333:4444:5555:6666::8888 should be valid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666::8888"));
-        assertTrue("IPV6 1111:2222:3333:4444:5555::8888 should be valid", validator.isValidInet6Address("1111:2222:3333:4444:5555::8888"));
-        assertTrue("IPV6 1111:2222:3333:4444::8888 should be valid", validator.isValidInet6Address("1111:2222:3333:4444::8888"));
-        assertTrue("IPV6 1111:2222:3333::8888 should be valid", validator.isValidInet6Address("1111:2222:3333::8888"));
-        assertTrue("IPV6 1111:2222::8888 should be valid", validator.isValidInet6Address("1111:2222::8888"));
-        assertTrue("IPV6 1111::8888 should be valid", validator.isValidInet6Address("1111::8888"));
-        assertTrue("IPV6 ::8888 should be valid", validator.isValidInet6Address("::8888"));
-        assertTrue("IPV6 1111:2222:3333:4444:5555::7777:8888 should be valid", validator.isValidInet6Address("1111:2222:3333:4444:5555::7777:8888"));
-        assertTrue("IPV6 1111:2222:3333:4444::7777:8888 should be valid", validator.isValidInet6Address("1111:2222:3333:4444::7777:8888"));
-        assertTrue("IPV6 1111:2222:3333::7777:8888 should be valid", validator.isValidInet6Address("1111:2222:3333::7777:8888"));
-        assertTrue("IPV6 1111:2222::7777:8888 should be valid", validator.isValidInet6Address("1111:2222::7777:8888"));
-        assertTrue("IPV6 1111::7777:8888 should be valid", validator.isValidInet6Address("1111::7777:8888"));
-        assertTrue("IPV6 ::7777:8888 should be valid", validator.isValidInet6Address("::7777:8888"));
-        assertTrue("IPV6 1111:2222:3333:4444::6666:7777:8888 should be valid", validator.isValidInet6Address("1111:2222:3333:4444::6666:7777:8888"));
-        assertTrue("IPV6 1111:2222:3333::6666:7777:8888 should be valid", validator.isValidInet6Address("1111:2222:3333::6666:7777:8888"));
-        assertTrue("IPV6 1111:2222::6666:7777:8888 should be valid", validator.isValidInet6Address("1111:2222::6666:7777:8888"));
-        assertTrue("IPV6 1111::6666:7777:8888 should be valid", validator.isValidInet6Address("1111::6666:7777:8888"));
-        assertTrue("IPV6 ::6666:7777:8888 should be valid", validator.isValidInet6Address("::6666:7777:8888"));
-        assertTrue("IPV6 1111:2222:3333::5555:6666:7777:8888 should be valid", validator.isValidInet6Address("1111:2222:3333::5555:6666:7777:8888"));
-        assertTrue("IPV6 1111:2222::5555:6666:7777:8888 should be valid", validator.isValidInet6Address("1111:2222::5555:6666:7777:8888"));
-        assertTrue("IPV6 1111::5555:6666:7777:8888 should be valid", validator.isValidInet6Address("1111::5555:6666:7777:8888"));
-        assertTrue("IPV6 ::5555:6666:7777:8888 should be valid", validator.isValidInet6Address("::5555:6666:7777:8888"));
-        assertTrue("IPV6 1111:2222::4444:5555:6666:7777:8888 should be valid", validator.isValidInet6Address("1111:2222::4444:5555:6666:7777:8888"));
-        assertTrue("IPV6 1111::4444:5555:6666:7777:8888 should be valid", validator.isValidInet6Address("1111::4444:5555:6666:7777:8888"));
-        assertTrue("IPV6 ::4444:5555:6666:7777:8888 should be valid", validator.isValidInet6Address("::4444:5555:6666:7777:8888"));
-        assertTrue("IPV6 1111::3333:4444:5555:6666:7777:8888 should be valid", validator.isValidInet6Address("1111::3333:4444:5555:6666:7777:8888"));
-        assertTrue("IPV6 ::3333:4444:5555:6666:7777:8888 should be valid", validator.isValidInet6Address("::3333:4444:5555:6666:7777:8888"));
-        assertTrue("IPV6 ::2222:3333:4444:5555:6666:7777:8888 should be valid", validator.isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888"));
-        assertTrue("IPV6 1111:2222:3333:4444:5555:6666:123.123.123.123 should be valid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:123.123.123.123"));
-        assertTrue("IPV6 1111:2222:3333:4444:5555::123.123.123.123 should be valid", validator.isValidInet6Address("1111:2222:3333:4444:5555::123.123.123.123"));
-        assertTrue("IPV6 1111:2222:3333:4444::123.123.123.123 should be valid", validator.isValidInet6Address("1111:2222:3333:4444::123.123.123.123"));
-        assertTrue("IPV6 1111:2222:3333::123.123.123.123 should be valid", validator.isValidInet6Address("1111:2222:3333::123.123.123.123"));
-        assertTrue("IPV6 1111:2222::123.123.123.123 should be valid", validator.isValidInet6Address("1111:2222::123.123.123.123"));
-        assertTrue("IPV6 1111::123.123.123.123 should be valid", validator.isValidInet6Address("1111::123.123.123.123"));
-        assertTrue("IPV6 ::123.123.123.123 should be valid", validator.isValidInet6Address("::123.123.123.123"));
-        assertTrue("IPV6 1111:2222:3333:4444::6666:123.123.123.123 should be valid", validator.isValidInet6Address("1111:2222:3333:4444::6666:123.123.123.123"));
-        assertTrue("IPV6 1111:2222:3333::6666:123.123.123.123 should be valid", validator.isValidInet6Address("1111:2222:3333::6666:123.123.123.123"));
-        assertTrue("IPV6 1111:2222::6666:123.123.123.123 should be valid", validator.isValidInet6Address("1111:2222::6666:123.123.123.123"));
-        assertTrue("IPV6 1111::6666:123.123.123.123 should be valid", validator.isValidInet6Address("1111::6666:123.123.123.123"));
-        assertTrue("IPV6 ::6666:123.123.123.123 should be valid", validator.isValidInet6Address("::6666:123.123.123.123"));
-        assertTrue("IPV6 1111:2222:3333::5555:6666:123.123.123.123 should be valid", validator.isValidInet6Address("1111:2222:3333::5555:6666:123.123.123.123"));
-        assertTrue("IPV6 1111:2222::5555:6666:123.123.123.123 should be valid", validator.isValidInet6Address("1111:2222::5555:6666:123.123.123.123"));
-        assertTrue("IPV6 1111::5555:6666:123.123.123.123 should be valid", validator.isValidInet6Address("1111::5555:6666:123.123.123.123"));
-        assertTrue("IPV6 ::5555:6666:123.123.123.123 should be valid", validator.isValidInet6Address("::5555:6666:123.123.123.123"));
-        assertTrue("IPV6 1111:2222::4444:5555:6666:123.123.123.123 should be valid", validator.isValidInet6Address("1111:2222::4444:5555:6666:123.123.123.123"));
-        assertTrue("IPV6 1111::4444:5555:6666:123.123.123.123 should be valid", validator.isValidInet6Address("1111::4444:5555:6666:123.123.123.123"));
-        assertTrue("IPV6 ::4444:5555:6666:123.123.123.123 should be valid", validator.isValidInet6Address("::4444:5555:6666:123.123.123.123"));
-        assertTrue("IPV6 1111::3333:4444:5555:6666:123.123.123.123 should be valid", validator.isValidInet6Address("1111::3333:4444:5555:6666:123.123.123.123"));
-        assertTrue("IPV6 ::2222:3333:4444:5555:6666:123.123.123.123 should be valid", validator.isValidInet6Address("::2222:3333:4444:5555:6666:123.123.123.123"));
-        // Trying combinations of "0" and "::"
-        // These are all syntactically correct, but are bad form
-        // because "0" adjacent to "::" should be combined into "::"
-        assertTrue("IPV6 ::0:0:0:0:0:0:0 should be valid", validator.isValidInet6Address("::0:0:0:0:0:0:0"));
-        assertTrue("IPV6 ::0:0:0:0:0:0 should be valid", validator.isValidInet6Address("::0:0:0:0:0:0"));
-        assertTrue("IPV6 ::0:0:0:0:0 should be valid", validator.isValidInet6Address("::0:0:0:0:0"));
-        assertTrue("IPV6 ::0:0:0:0 should be valid", validator.isValidInet6Address("::0:0:0:0"));
-        assertTrue("IPV6 ::0:0:0 should be valid", validator.isValidInet6Address("::0:0:0"));
-        assertTrue("IPV6 ::0:0 should be valid", validator.isValidInet6Address("::0:0"));
-        assertTrue("IPV6 ::0 should be valid", validator.isValidInet6Address("::0"));
-        assertTrue("IPV6 0:0:0:0:0:0:0:: should be valid", validator.isValidInet6Address("0:0:0:0:0:0:0::"));
-        assertTrue("IPV6 0:0:0:0:0:0:: should be valid", validator.isValidInet6Address("0:0:0:0:0:0::"));
-        assertTrue("IPV6 0:0:0:0:0:: should be valid", validator.isValidInet6Address("0:0:0:0:0::"));
-        assertTrue("IPV6 0:0:0:0:: should be valid", validator.isValidInet6Address("0:0:0:0::"));
-        assertTrue("IPV6 0:0:0:: should be valid", validator.isValidInet6Address("0:0:0::"));
-        assertTrue("IPV6 0:0:: should be valid", validator.isValidInet6Address("0:0::"));
-        assertTrue("IPV6 0:: should be valid", validator.isValidInet6Address("0::"));
-        // Invalid data
-        assertFalse("IPV6 XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX should be invalid", validator.isValidInet6Address("XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX"));
-        // Too many components
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:7777:8888:9999 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:9999"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:7777:8888:: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888::"));
-        assertFalse("IPV6 ::2222:3333:4444:5555:6666:7777:8888:9999 should be invalid", validator.isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888:9999"));
-        // Too few components
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:7777 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555"));
-        assertFalse("IPV6 1111:2222:3333:4444 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444"));
-        assertFalse("IPV6 1111:2222:3333 should be invalid", validator.isValidInet6Address("1111:2222:3333"));
-        assertFalse("IPV6 1111:2222 should be invalid", validator.isValidInet6Address("1111:2222"));
-        assertFalse("IPV6 1111 should be invalid", validator.isValidInet6Address("1111"));
-        // Missing :
-        assertFalse("IPV6 11112222:3333:4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address("11112222:3333:4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 1111:22223333:4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address("1111:22223333:4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 1111:2222:33334444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address("1111:2222:33334444:5555:6666:7777:8888"));
-        assertFalse("IPV6 1111:2222:3333:44445555:6666:7777:8888 should be invalid", validator.isValidInet6Address("1111:2222:3333:44445555:6666:7777:8888"));
-        assertFalse("IPV6 1111:2222:3333:4444:55556666:7777:8888 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:55556666:7777:8888"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:66667777:8888 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:66667777:8888"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:77778888 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:77778888"));
-        // Missing : intended for ::
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:7777:8888: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:7777: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:"));
-        assertFalse("IPV6 1111:2222:3333:4444: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:"));
-        assertFalse("IPV6 1111:2222:3333: should be invalid", validator.isValidInet6Address("1111:2222:3333:"));
-        assertFalse("IPV6 1111:2222: should be invalid", validator.isValidInet6Address("1111:2222:"));
-        assertFalse("IPV6 :8888 should be invalid", validator.isValidInet6Address(":8888"));
-        assertFalse("IPV6 :7777:8888 should be invalid", validator.isValidInet6Address(":7777:8888"));
-        assertFalse("IPV6 :6666:7777:8888 should be invalid", validator.isValidInet6Address(":6666:7777:8888"));
-        assertFalse("IPV6 :5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":5555:6666:7777:8888"));
-        assertFalse("IPV6 :4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 :3333:4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":3333:4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 :2222:3333:4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":2222:3333:4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 :1111:2222:3333:4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666:7777:8888"));
-        // :::
-        assertFalse("IPV6 :::2222:3333:4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":::2222:3333:4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 1111:::3333:4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address("1111:::3333:4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 1111:2222:::4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address("1111:2222:::4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 1111:2222:3333:::5555:6666:7777:8888 should be invalid", validator.isValidInet6Address("1111:2222:3333:::5555:6666:7777:8888"));
-        assertFalse("IPV6 1111:2222:3333:4444:::6666:7777:8888 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:::6666:7777:8888"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:::7777:8888 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:::7777:8888"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:::8888 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:::8888"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:7777::: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:::"));
-        // Double ::
-        assertFalse("IPV6 ::2222::4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address("::2222::4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 ::2222:3333::5555:6666:7777:8888 should be invalid", validator.isValidInet6Address("::2222:3333::5555:6666:7777:8888"));
-        assertFalse("IPV6 ::2222:3333:4444::6666:7777:8888 should be invalid", validator.isValidInet6Address("::2222:3333:4444::6666:7777:8888"));
-        assertFalse("IPV6 ::2222:3333:4444:5555::7777:8888 should be invalid", validator.isValidInet6Address("::2222:3333:4444:5555::7777:8888"));
-        assertFalse("IPV6 ::2222:3333:4444:5555:7777::8888 should be invalid", validator.isValidInet6Address("::2222:3333:4444:5555:7777::8888"));
-        assertFalse("IPV6 ::2222:3333:4444:5555:7777:8888:: should be invalid", validator.isValidInet6Address("::2222:3333:4444:5555:7777:8888::"));
-        assertFalse("IPV6 1111::3333::5555:6666:7777:8888 should be invalid", validator.isValidInet6Address("1111::3333::5555:6666:7777:8888"));
-        assertFalse("IPV6 1111::3333:4444::6666:7777:8888 should be invalid", validator.isValidInet6Address("1111::3333:4444::6666:7777:8888"));
-        assertFalse("IPV6 1111::3333:4444:5555::7777:8888 should be invalid", validator.isValidInet6Address("1111::3333:4444:5555::7777:8888"));
-        assertFalse("IPV6 1111::3333:4444:5555:6666::8888 should be invalid", validator.isValidInet6Address("1111::3333:4444:5555:6666::8888"));
-        assertFalse("IPV6 1111::3333:4444:5555:6666:7777:: should be invalid", validator.isValidInet6Address("1111::3333:4444:5555:6666:7777::"));
-        assertFalse("IPV6 1111:2222::4444::6666:7777:8888 should be invalid", validator.isValidInet6Address("1111:2222::4444::6666:7777:8888"));
-        assertFalse("IPV6 1111:2222::4444:5555::7777:8888 should be invalid", validator.isValidInet6Address("1111:2222::4444:5555::7777:8888"));
-        assertFalse("IPV6 1111:2222::4444:5555:6666::8888 should be invalid", validator.isValidInet6Address("1111:2222::4444:5555:6666::8888"));
-        assertFalse("IPV6 1111:2222::4444:5555:6666:7777:: should be invalid", validator.isValidInet6Address("1111:2222::4444:5555:6666:7777::"));
-        assertFalse("IPV6 1111:2222:3333::5555::7777:8888 should be invalid", validator.isValidInet6Address("1111:2222:3333::5555::7777:8888"));
-        assertFalse("IPV6 1111:2222:3333::5555:6666::8888 should be invalid", validator.isValidInet6Address("1111:2222:3333::5555:6666::8888"));
-        assertFalse("IPV6 1111:2222:3333::5555:6666:7777:: should be invalid", validator.isValidInet6Address("1111:2222:3333::5555:6666:7777::"));
-        assertFalse("IPV6 1111:2222:3333:4444::6666::8888 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444::6666::8888"));
-        assertFalse("IPV6 1111:2222:3333:4444::6666:7777:: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444::6666:7777::"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555::7777:: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555::7777::"));
-        // Too many components"
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:8888:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:7777:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666::1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666::1.2.3.4"));
-        assertFalse("IPV6 ::2222:3333:4444:5555:6666:7777:1.2.3.4 should be invalid", validator.isValidInet6Address("::2222:3333:4444:5555:6666:7777:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:1.2.3.4.5 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:1.2.3.4.5"));
-        // Too few components
-        assertFalse("IPV6 1111:2222:3333:4444:5555:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:4444:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:1.2.3.4"));
-        assertFalse("IPV6 1111:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:1.2.3.4"));
-        assertFalse("IPV6 1.2.3.4 should be invalid", validator.isValidInet6Address("1.2.3.4"));
-        // Missing :
-        assertFalse("IPV6 11112222:3333:4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address("11112222:3333:4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 1111:22223333:4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:22223333:4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:33334444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:33334444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:44445555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:44445555:6666:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:4444:55556666:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:55556666:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:66661.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:66661.2.3.4"));
-        // Missing .
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:255255.255.255 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:255255.255.255"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:255.255255.255 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:255.255255.255"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:255.255.255255 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:255.255.255255"));
-        // Missing : intended for ::
-        assertFalse("IPV6 :1.2.3.4 should be invalid", validator.isValidInet6Address(":1.2.3.4"));
-        assertFalse("IPV6 :6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":6666:1.2.3.4"));
-        assertFalse("IPV6 :5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :3333:4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":3333:4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :2222:3333:4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":2222:3333:4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :1111:2222:3333:4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666:1.2.3.4"));
-        // :::
-        assertFalse("IPV6 :::2222:3333:4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":::2222:3333:4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 1111:::3333:4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:::3333:4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:::4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:::4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:::5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:::5555:6666:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:4444:::6666:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:::6666:1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:::1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:::1.2.3.4"));
-        // Double ::
-        assertFalse("IPV6 ::2222::4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address("::2222::4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 ::2222:3333::5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address("::2222:3333::5555:6666:1.2.3.4"));
-        assertFalse("IPV6 ::2222:3333:4444::6666:1.2.3.4 should be invalid", validator.isValidInet6Address("::2222:3333:4444::6666:1.2.3.4"));
-        assertFalse("IPV6 ::2222:3333:4444:5555::1.2.3.4 should be invalid", validator.isValidInet6Address("::2222:3333:4444:5555::1.2.3.4"));
-        assertFalse("IPV6 1111::3333::5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address("1111::3333::5555:6666:1.2.3.4"));
-        assertFalse("IPV6 1111::3333:4444::6666:1.2.3.4 should be invalid", validator.isValidInet6Address("1111::3333:4444::6666:1.2.3.4"));
-        assertFalse("IPV6 1111::3333:4444:5555::1.2.3.4 should be invalid", validator.isValidInet6Address("1111::3333:4444:5555::1.2.3.4"));
-        assertFalse("IPV6 1111:2222::4444::6666:1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222::4444::6666:1.2.3.4"));
-        assertFalse("IPV6 1111:2222::4444:5555::1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222::4444:5555::1.2.3.4"));
-        assertFalse("IPV6 1111:2222:3333::5555::1.2.3.4 should be invalid", validator.isValidInet6Address("1111:2222:3333::5555::1.2.3.4"));
-        // Missing parts
-        assertFalse("IPV6 ::. should be invalid", validator.isValidInet6Address("::."));
-        assertFalse("IPV6 ::.. should be invalid", validator.isValidInet6Address("::.."));
-        assertFalse("IPV6 ::... should be invalid", validator.isValidInet6Address("::..."));
-        assertFalse("IPV6 ::1... should be invalid", validator.isValidInet6Address("::1..."));
-        assertFalse("IPV6 ::1.2.. should be invalid", validator.isValidInet6Address("::1.2.."));
-        assertFalse("IPV6 ::1.2.3. should be invalid", validator.isValidInet6Address("::1.2.3."));
-        assertFalse("IPV6 ::.2.. should be invalid", validator.isValidInet6Address("::.2.."));
-        assertFalse("IPV6 ::.2.3. should be invalid", validator.isValidInet6Address("::.2.3."));
-        assertFalse("IPV6 ::.2.3.4 should be invalid", validator.isValidInet6Address("::.2.3.4"));
-        assertFalse("IPV6 ::..3. should be invalid", validator.isValidInet6Address("::..3."));
-        assertFalse("IPV6 ::..3.4 should be invalid", validator.isValidInet6Address("::..3.4"));
-        assertFalse("IPV6 ::...4 should be invalid", validator.isValidInet6Address("::...4"));
-        // Extra : in front
-        assertFalse("IPV6 :1111:2222:3333:4444:5555:6666:7777:: should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666:7777::"));
-        assertFalse("IPV6 :1111:2222:3333:4444:5555:6666:: should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666::"));
-        assertFalse("IPV6 :1111:2222:3333:4444:5555:: should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444:5555::"));
-        assertFalse("IPV6 :1111:2222:3333:4444:: should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444::"));
-        assertFalse("IPV6 :1111:2222:3333:: should be invalid", validator.isValidInet6Address(":1111:2222:3333::"));
-        assertFalse("IPV6 :1111:2222:: should be invalid", validator.isValidInet6Address(":1111:2222::"));
-        assertFalse("IPV6 :1111:: should be invalid", validator.isValidInet6Address(":1111::"));
-        assertFalse("IPV6 :1111:2222:3333:4444:5555:6666::8888 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666::8888"));
-        assertFalse("IPV6 :1111:2222:3333:4444:5555::8888 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444:5555::8888"));
-        assertFalse("IPV6 :1111:2222:3333:4444::8888 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444::8888"));
-        assertFalse("IPV6 :1111:2222:3333::8888 should be invalid", validator.isValidInet6Address(":1111:2222:3333::8888"));
-        assertFalse("IPV6 :1111:2222::8888 should be invalid", validator.isValidInet6Address(":1111:2222::8888"));
-        assertFalse("IPV6 :1111::8888 should be invalid", validator.isValidInet6Address(":1111::8888"));
-        assertFalse("IPV6 :::8888 should be invalid", validator.isValidInet6Address(":::8888"));
-        assertFalse("IPV6 :1111:2222:3333:4444:5555::7777:8888 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444:5555::7777:8888"));
-        assertFalse("IPV6 :1111:2222:3333:4444::7777:8888 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444::7777:8888"));
-        assertFalse("IPV6 :1111:2222:3333::7777:8888 should be invalid", validator.isValidInet6Address(":1111:2222:3333::7777:8888"));
-        assertFalse("IPV6 :1111:2222::7777:8888 should be invalid", validator.isValidInet6Address(":1111:2222::7777:8888"));
-        assertFalse("IPV6 :1111::7777:8888 should be invalid", validator.isValidInet6Address(":1111::7777:8888"));
-        assertFalse("IPV6 :::7777:8888 should be invalid", validator.isValidInet6Address(":::7777:8888"));
-        assertFalse("IPV6 :1111:2222:3333:4444::6666:7777:8888 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444::6666:7777:8888"));
-        assertFalse("IPV6 :1111:2222:3333::6666:7777:8888 should be invalid", validator.isValidInet6Address(":1111:2222:3333::6666:7777:8888"));
-        assertFalse("IPV6 :1111:2222::6666:7777:8888 should be invalid", validator.isValidInet6Address(":1111:2222::6666:7777:8888"));
-        assertFalse("IPV6 :1111::6666:7777:8888 should be invalid", validator.isValidInet6Address(":1111::6666:7777:8888"));
-        assertFalse("IPV6 :::6666:7777:8888 should be invalid", validator.isValidInet6Address(":::6666:7777:8888"));
-        assertFalse("IPV6 :1111:2222:3333::5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":1111:2222:3333::5555:6666:7777:8888"));
-        assertFalse("IPV6 :1111:2222::5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":1111:2222::5555:6666:7777:8888"));
-        assertFalse("IPV6 :1111::5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":1111::5555:6666:7777:8888"));
-        assertFalse("IPV6 :::5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":::5555:6666:7777:8888"));
-        assertFalse("IPV6 :1111:2222::4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":1111:2222::4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 :1111::4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":1111::4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 :::4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":::4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 :1111::3333:4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":1111::3333:4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 :::3333:4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":::3333:4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 :::2222:3333:4444:5555:6666:7777:8888 should be invalid", validator.isValidInet6Address(":::2222:3333:4444:5555:6666:7777:8888"));
-        assertFalse("IPV6 :1111:2222:3333:4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :1111:2222:3333:4444:5555::1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444:5555::1.2.3.4"));
-        assertFalse("IPV6 :1111:2222:3333:4444::1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444::1.2.3.4"));
-        assertFalse("IPV6 :1111:2222:3333::1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222:3333::1.2.3.4"));
-        assertFalse("IPV6 :1111:2222::1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222::1.2.3.4"));
-        assertFalse("IPV6 :1111::1.2.3.4 should be invalid", validator.isValidInet6Address(":1111::1.2.3.4"));
-        assertFalse("IPV6 :::1.2.3.4 should be invalid", validator.isValidInet6Address(":::1.2.3.4"));
-        assertFalse("IPV6 :1111:2222:3333:4444::6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222:3333:4444::6666:1.2.3.4"));
-        assertFalse("IPV6 :1111:2222:3333::6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222:3333::6666:1.2.3.4"));
-        assertFalse("IPV6 :1111:2222::6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222::6666:1.2.3.4"));
-        assertFalse("IPV6 :1111::6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111::6666:1.2.3.4"));
-        assertFalse("IPV6 :::6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":::6666:1.2.3.4"));
-        assertFalse("IPV6 :1111:2222:3333::5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222:3333::5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :1111:2222::5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222::5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :1111::5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111::5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :::5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":::5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :1111:2222::4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111:2222::4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :1111::4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111::4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :::4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":::4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :1111::3333:4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":1111::3333:4444:5555:6666:1.2.3.4"));
-        assertFalse("IPV6 :::2222:3333:4444:5555:6666:1.2.3.4 should be invalid", validator.isValidInet6Address(":::2222:3333:4444:5555:6666:1.2.3.4"));
-        // Extra : at end
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666:7777::: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:7777:::"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666::: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666:::"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555::: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:::"));
-        assertFalse("IPV6 1111:2222:3333:4444::: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:::"));
-        assertFalse("IPV6 1111:2222:3333::: should be invalid", validator.isValidInet6Address("1111:2222:3333:::"));
-        assertFalse("IPV6 1111:2222::: should be invalid", validator.isValidInet6Address("1111:2222:::"));
-        assertFalse("IPV6 1111::: should be invalid", validator.isValidInet6Address("1111:::"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555:6666::8888: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555:6666::8888:"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555::8888: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555::8888:"));
-        assertFalse("IPV6 1111:2222:3333:4444::8888: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444::8888:"));
-        assertFalse("IPV6 1111:2222:3333::8888: should be invalid", validator.isValidInet6Address("1111:2222:3333::8888:"));
-        assertFalse("IPV6 1111:2222::8888: should be invalid", validator.isValidInet6Address("1111:2222::8888:"));
-        assertFalse("IPV6 1111::8888: should be invalid", validator.isValidInet6Address("1111::8888:"));
-        assertFalse("IPV6 ::8888: should be invalid", validator.isValidInet6Address("::8888:"));
-        assertFalse("IPV6 1111:2222:3333:4444:5555::7777:8888: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444:5555::7777:8888:"));
-        assertFalse("IPV6 1111:2222:3333:4444::7777:8888: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444::7777:8888:"));
-        assertFalse("IPV6 1111:2222:3333::7777:8888: should be invalid", validator.isValidInet6Address("1111:2222:3333::7777:8888:"));
-        assertFalse("IPV6 1111:2222::7777:8888: should be invalid", validator.isValidInet6Address("1111:2222::7777:8888:"));
-        assertFalse("IPV6 1111::7777:8888: should be invalid", validator.isValidInet6Address("1111::7777:8888:"));
-        assertFalse("IPV6 ::7777:8888: should be invalid", validator.isValidInet6Address("::7777:8888:"));
-        assertFalse("IPV6 1111:2222:3333:4444::6666:7777:8888: should be invalid", validator.isValidInet6Address("1111:2222:3333:4444::6666:7777:8888:"));
-        assertFalse("IPV6 1111:2222:3333::6666:7777:8888: should be invalid", validator.isValidInet6Address("1111:2222:3333::6666:7777:8888:"));
-        assertFalse("IPV6 1111:2222::6666:7777:8888: should be invalid", validator.isValidInet6Address("1111:2222::6666:7777:8888:"));
-        assertFalse("IPV6 1111::6666:7777:8888: should be invalid", validator.isValidInet6Address("1111::6666:7777:8888:"));
-        assertFalse("IPV6 ::6666:7777:8888: should be invalid", validator.isValidInet6Address("::6666:7777:8888:"));
-        assertFalse("IPV6 1111:2222:3333::5555:6666:7777:8888: should be invalid", validator.isValidInet6Address("1111:2222:3333::5555:6666:7777:8888:"));
-        assertFalse("IPV6 1111:2222::5555:6666:7777:8888: should be invalid", validator.isValidInet6Address("1111:2222::5555:6666:7777:8888:"));
-        assertFalse("IPV6 1111::5555:6666:7777:8888: should be invalid", validator.isValidInet6Address("1111::5555:6666:7777:8888:"));
-        assertFalse("IPV6 ::5555:6666:7777:8888: should be invalid", validator.isValidInet6Address("::5555:6666:7777:8888:"));
-        assertFalse("IPV6 1111:2222::4444:5555:6666:7777:8888: should be invalid", validator.isValidInet6Address("1111:2222::4444:5555:6666:7777:8888:"));
-        assertFalse("IPV6 1111::4444:5555:6666:7777:8888: should be invalid", validator.isValidInet6Address("1111::4444:5555:6666:7777:8888:"));
-        assertFalse("IPV6 ::4444:5555:6666:7777:8888: should be invalid", validator.isValidInet6Address("::4444:5555:6666:7777:8888:"));
-        assertFalse("IPV6 1111::3333:4444:5555:6666:7777:8888: should be invalid", validator.isValidInet6Address("1111::3333:4444:5555:6666:7777:8888:"));
-        assertFalse("IPV6 ::3333:4444:5555:6666:7777:8888: should be invalid", validator.isValidInet6Address("::3333:4444:5555:6666:7777:8888:"));
-        assertFalse("IPV6 ::2222:3333:4444:5555:6666:7777:8888: should be invalid", validator.isValidInet6Address("::2222:3333:4444:5555:6666:7777:8888:"));
-        assertTrue("IPV6 0:a:b:c:d:e:f:: should be valid", validator.isValidInet6Address("0:a:b:c:d:e:f::"));
-        assertTrue("IPV6 ::0:a:b:c:d:e:f should be valid", validator.isValidInet6Address("::0:a:b:c:d:e:f")); // syntactically correct, but bad form (::0:... could be combined)
-        assertTrue("IPV6 a:b:c:d:e:f:0:: should be valid", validator.isValidInet6Address("a:b:c:d:e:f:0::"));
-        assertFalse("IPV6 ':10.0.0.1 should be invalid", validator.isValidInet6Address("':10.0.0.1"));
+    @Test
+    public void testVALIDATOR_445() {
+        final String[] valid = { "2001:0000:1234:0000:0000:C1C0:ABCD:0876", "2001:0000:1234:0000:0000:C1C0:ABCD:0876/123",
+                "2001:0000:1234:0000:0000:C1C0:ABCD:0876/0", "2001:0000:1234:0000:0000:C1C0:ABCD:0876%0", "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abcdefgh", };
+        final String[] invalid = { "2001:0000:1234:0000:0000:C1C0:ABCD:0876/129", // too big
+                "2001:0000:1234:0000:0000:C1C0:ABCD:0876/-0", // sign not allowed
+                "2001:0000:1234:0000:0000:C1C0:ABCD:0876/+0", // sign not allowed
+                "2001:0000:1234:0000:0000:C1C0:ABCD:0876/10O", // non-digit
+                "2001:0000:1234:0000:0000:C1C0:ABCD:0876/0%0", // /bits before %node-id
+                "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abc defgh", // space in node id
+                "2001:0000:1234:0000:0000:C1C0:ABCD:0876%abc%defgh", // '%' in node id
+        };
+        for (final String item : valid) {
+            assertTrue(validator.isValid(item), () -> String.format("%s should be valid", item));
+        }
+        for (final String item : invalid) {
+            assertFalse(validator.isValid(item), () -> String.format("%s should be invalid", item));
+        }
     }
 }
-
-
diff --git a/src/test/java/org/apache/commons/validator/routines/IntegerValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/IntegerValidatorTest.java
index 7fed0d6..ac61128 100644
--- a/src/test/java/org/apache/commons/validator/routines/IntegerValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/IntegerValidatorTest.java
@@ -16,8 +16,16 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.util.Locale;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Test Case for IntegerValidator.
  */
@@ -25,26 +33,19 @@
 
     private static final Integer INT_MIN_VAL = Integer.valueOf(Integer.MIN_VALUE);
     private static final Integer INT_MAX_VAL = Integer.valueOf(Integer.MAX_VALUE);
-    private static final String INT_MAX   =  "2147483647";
-    private static final String INT_MAX_0 =  "2147483647.99999999999999999999999"; // force double rounding
-    private static final String INT_MAX_1 =  "2147483648";
-    private static final String INT_MIN   = "-2147483648";
+    private static final String INT_MAX = "2147483647";
+    private static final String INT_MAX_0 = "2147483647.99999999999999999999999"; // force double rounding
+    private static final String INT_MAX_1 = "2147483648";
+    private static final String INT_MIN = "-2147483648";
     private static final String INT_MIN_0 = "-2147483648.99999999999999999999999"; // force double rounding";
     private static final String INT_MIN_1 = "-2147483649";
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public IntegerValidatorTest(final String name) {
-        super(name);
-    }
-
     @Override
-    protected void setUp() throws Exception {
+    @BeforeEach
+    protected void setUp() {
         super.setUp();
 
-        validator       = new IntegerValidator(false, 0);
+        validator = new IntegerValidator(false, 0);
         strictValidator = new IntegerValidator();
 
         testPattern = "#,###";
@@ -56,18 +57,18 @@
         minMinusOne = Long.valueOf(min.longValue() - 1);
 
         // testInvalidStrict()
-        invalidStrict = new String[] {null, "", "X", "X12", "12X", "1X2", "1.2", INT_MAX_1, INT_MIN_1};
+        invalidStrict = new String[] { null, "", "X", "X12", "12X", "1X2", "1.2", INT_MAX_1, INT_MIN_1 };
 
         // testInvalidNotStrict()
-        invalid       = new String[] {null, "", "X", "X12", INT_MAX_1, INT_MIN_1};
+        invalid = new String[] { null, "", "X", "X12", INT_MAX_1, INT_MIN_1 };
 
         // testValid()
-        testNumber    = Integer.valueOf(1234);
-        testZero      = Integer.valueOf(0);
-        validStrict          = new String[] {"0", "1234", "1,234", INT_MAX, INT_MIN};
-        validStrictCompare   = new Number[] {testZero, testNumber, testNumber, INT_MAX_VAL, INT_MIN_VAL};
-        valid                = new String[] {"0", "1234", "1,234", "1,234.5", "1234X", INT_MAX, INT_MIN, INT_MAX_0, INT_MIN_0};
-        validCompare         = new Number[] {testZero, testNumber, testNumber, testNumber, testNumber, INT_MAX_VAL, INT_MIN_VAL, INT_MAX_VAL, INT_MIN_VAL};
+        testNumber = Integer.valueOf(1234);
+        testZero = Integer.valueOf(0);
+        validStrict = new String[] { "0", "1234", "1,234", INT_MAX, INT_MIN };
+        validStrictCompare = new Number[] { testZero, testNumber, testNumber, INT_MAX_VAL, INT_MIN_VAL };
+        valid = new String[] { "0", "1234", "1,234", "1,234.5", "1234X", INT_MAX, INT_MIN, INT_MAX_0, INT_MIN_0 };
+        validCompare = new Number[] { testZero, testNumber, testNumber, testNumber, testNumber, INT_MAX_VAL, INT_MIN_VAL, INT_MAX_VAL, INT_MIN_VAL };
 
         testStringUS = "1,234";
         testStringDE = "1.234";
@@ -75,49 +76,17 @@
         // Localized Pattern test
         localeValue = testStringDE;
         localePattern = "#.###";
-        testLocale    = Locale.GERMANY;
+        testLocale = Locale.GERMANY;
         localeExpected = testNumber;
     }
 
     /**
-     * Test IntegerValidator validate Methods
-     */
-    public void testIntegerValidatorMethods() {
-        final Locale locale     = Locale.GERMAN;
-        final String pattern    = "0,00,00";
-        final String patternVal = "1,23,45";
-        final String germanPatternVal = "1.23.45";
-        final String localeVal  = "12.345";
-        final String defaultVal = "12,345";
-        final String XXXX    = "XXXX";
-        final Integer expected = Integer.valueOf(12345);
-        assertEquals("validate(A) default", expected, IntegerValidator.getInstance().validate(defaultVal));
-        assertEquals("validate(A) locale ", expected, IntegerValidator.getInstance().validate(localeVal, locale));
-        assertEquals("validate(A) pattern", expected, IntegerValidator.getInstance().validate(patternVal, pattern));
-        assertEquals("validate(A) both",    expected, IntegerValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertTrue("isValid(A) default", IntegerValidator.getInstance().isValid(defaultVal));
-        assertTrue("isValid(A) locale ", IntegerValidator.getInstance().isValid(localeVal, locale));
-        assertTrue("isValid(A) pattern", IntegerValidator.getInstance().isValid(patternVal, pattern));
-        assertTrue("isValid(A) both",    IntegerValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertNull("validate(B) default", IntegerValidator.getInstance().validate(XXXX));
-        assertNull("validate(B) locale ", IntegerValidator.getInstance().validate(XXXX, locale));
-        assertNull("validate(B) pattern", IntegerValidator.getInstance().validate(XXXX, pattern));
-        assertNull("validate(B) both",    IntegerValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN));
-
-        assertFalse("isValid(B) default", IntegerValidator.getInstance().isValid(XXXX));
-        assertFalse("isValid(B) locale ", IntegerValidator.getInstance().isValid(XXXX, locale));
-        assertFalse("isValid(B) pattern", IntegerValidator.getInstance().isValid(XXXX, pattern));
-        assertFalse("isValid(B) both",    IntegerValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN));
-    }
-
-    /**
      * Test Integer Range/Min/Max
      */
+    @Test
     public void testIntegerRangeMinMax() {
-        final IntegerValidator validator = (IntegerValidator)strictValidator;
-        final Integer number9  = validator.validate("9", "#");
+        final IntegerValidator validator = (IntegerValidator) strictValidator;
+        final Integer number9 = validator.validate("9", "#");
         final Integer number10 = validator.validate("10", "#");
         final Integer number11 = validator.validate("11", "#");
         final Integer number19 = validator.validate("19", "#");
@@ -125,26 +94,62 @@
         final Integer number21 = validator.validate("21", "#");
 
         // Test isInRange()
-        assertFalse("isInRange() < min",   validator.isInRange(number9,  10, 20));
-        assertTrue("isInRange() = min",    validator.isInRange(number10, 10, 20));
-        assertTrue("isInRange() in range", validator.isInRange(number11, 10, 20));
-        assertTrue("isInRange() = max",    validator.isInRange(number20, 10, 20));
-        assertFalse("isInRange() > max",   validator.isInRange(number21, 10, 20));
+        assertFalse(validator.isInRange(number9, 10, 20), "isInRange() < min");
+        assertTrue(validator.isInRange(number10, 10, 20), "isInRange() = min");
+        assertTrue(validator.isInRange(number11, 10, 20), "isInRange() in range");
+        assertTrue(validator.isInRange(number20, 10, 20), "isInRange() = max");
+        assertFalse(validator.isInRange(number21, 10, 20), "isInRange() > max");
 
         // Test minValue()
-        assertFalse("minValue() < min",    validator.minValue(number9,  10));
-        assertTrue("minValue() = min",     validator.minValue(number10, 10));
-        assertTrue("minValue() > min",     validator.minValue(number11, 10));
+        assertFalse(validator.minValue(number9, 10), "minValue() < min");
+        assertTrue(validator.minValue(number10, 10), "minValue() = min");
+        assertTrue(validator.minValue(number11, 10), "minValue() > min");
 
         // Test minValue()
-        assertTrue("maxValue() < max",     validator.maxValue(number19, 20));
-        assertTrue("maxValue() = max",     validator.maxValue(number20, 20));
-        assertFalse("maxValue() > max",    validator.maxValue(number21, 20));
+        assertTrue(validator.maxValue(number19, 20), "maxValue() < max");
+        assertTrue(validator.maxValue(number20, 20), "maxValue() = max");
+        assertFalse(validator.maxValue(number21, 20), "maxValue() > max");
     }
+
+    /**
+     * Test IntegerValidator validate Methods
+     */
+    @Test
+    public void testIntegerValidatorMethods() {
+        final Locale locale = Locale.GERMAN;
+        final String pattern = "0,00,00";
+        final String patternVal = "1,23,45";
+        final String germanPatternVal = "1.23.45";
+        final String localeVal = "12.345";
+        final String defaultVal = "12,345";
+        final String XXXX = "XXXX";
+        final Integer expected = Integer.valueOf(12345);
+        assertEquals(expected, IntegerValidator.getInstance().validate(defaultVal), "validate(A) default");
+        assertEquals(expected, IntegerValidator.getInstance().validate(localeVal, locale), "validate(A) locale");
+        assertEquals(expected, IntegerValidator.getInstance().validate(patternVal, pattern), "validate(A) pattern");
+        assertEquals(expected, IntegerValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN), "validate(A) both");
+
+        assertTrue(IntegerValidator.getInstance().isValid(defaultVal), "isValid(A) default");
+        assertTrue(IntegerValidator.getInstance().isValid(localeVal, locale), "isValid(A) locale");
+        assertTrue(IntegerValidator.getInstance().isValid(patternVal, pattern), "isValid(A) pattern");
+        assertTrue(IntegerValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN), "isValid(A) both");
+
+        assertNull(IntegerValidator.getInstance().validate(XXXX), "validate(B) default");
+        assertNull(IntegerValidator.getInstance().validate(XXXX, locale), "validate(B) locale");
+        assertNull(IntegerValidator.getInstance().validate(XXXX, pattern), "validate(B) pattern");
+        assertNull(IntegerValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN), "validate(B) both");
+
+        assertFalse(IntegerValidator.getInstance().isValid(XXXX), "isValid(B) default");
+        assertFalse(IntegerValidator.getInstance().isValid(XXXX, locale), "isValid(B) locale");
+        assertFalse(IntegerValidator.getInstance().isValid(XXXX, pattern), "isValid(B) pattern");
+        assertFalse(IntegerValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN), "isValid(B) both");
+    }
+
+    @Test
     public void testMinMaxValues() {
-        assertTrue("2147483647 is max integer", validator.isValid("2147483647"));
-        assertFalse("2147483648 > max integer", validator.isValid("2147483648"));
-        assertTrue("-2147483648 is min integer", validator.isValid("-2147483648"));
-        assertFalse("-2147483649 < min integer", validator.isValid("-2147483649"));
+        assertTrue(validator.isValid("2147483647"), "2147483647 is max integer");
+        assertFalse(validator.isValid("2147483648"), "2147483648 > max integer");
+        assertTrue(validator.isValid("-2147483648"), "-2147483648 is min integer");
+        assertFalse(validator.isValid("-2147483649"), "-2147483649 < min integer");
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/LongValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/LongValidatorTest.java
index 1879400..1b2ec24 100644
--- a/src/test/java/org/apache/commons/validator/routines/LongValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/LongValidatorTest.java
@@ -16,8 +16,16 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.util.Locale;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Test Case for LongValidator.
  */
@@ -25,51 +33,44 @@
 
     private static final Long LONG_MIN_VAL = Long.valueOf(Long.MIN_VALUE);
     private static final Long LONG_MAX_VAL = Long.valueOf(Long.MAX_VALUE);
-    private static final String LONG_MAX   =  "9223372036854775807";
-    private static final String LONG_MAX_0 =  "9223372036854775807.99999999999999999999999"; // force double rounding
-    private static final String LONG_MAX_1 =  "9223372036854775808";
-    private static final String LONG_MIN   = "-9223372036854775808";
+    private static final String LONG_MAX = "9223372036854775807";
+    private static final String LONG_MAX_0 = "9223372036854775807.99999999999999999999999"; // force double rounding
+    private static final String LONG_MAX_1 = "9223372036854775808";
+    private static final String LONG_MIN = "-9223372036854775808";
     private static final String LONG_MIN_0 = "-9223372036854775808.99999999999999999999999"; // force double rounding
     private static final String LONG_MIN_1 = "-9223372036854775809";
 
     private static final String NINES = "9999999999999999999999999999999999999";
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public LongValidatorTest(final String name) {
-        super(name);
-    }
 
     @Override
-    protected void setUp() throws Exception {
+    @BeforeEach
+    protected void setUp() {
         super.setUp();
 
-        validator       = new LongValidator(false, 0);
+        validator = new LongValidator(false, 0);
         strictValidator = new LongValidator();
 
         testPattern = "#,###";
 
         // testValidateMinMax()
-        max =  null;
+        max = null;
         maxPlusOne = null;
         min = null;
         minMinusOne = null;
 
-
         // testInvalidStrict()
-        invalidStrict = new String[] {null, "", "X", "X12", "12X", "1X2", "1.2", LONG_MAX_1, LONG_MIN_1, NINES};
+        invalidStrict = new String[] { null, "", "X", "X12", "12X", "1X2", "1.2", LONG_MAX_1, LONG_MIN_1, NINES };
 
         // testInvalidNotStrict()
-        invalid       = new String[] {null, "", "X", "X12", "", LONG_MAX_1, LONG_MIN_1, NINES};
+        invalid = new String[] { null, "", "X", "X12", "", LONG_MAX_1, LONG_MIN_1, NINES };
 
         // testValid()
-        testNumber    = Long.valueOf(1234);
-        testZero      = Long.valueOf(0);
-        validStrict          = new String[] {"0", "1234", "1,234", LONG_MAX, LONG_MIN};
-        validStrictCompare   = new Number[] {testZero, testNumber, testNumber, LONG_MAX_VAL, LONG_MIN_VAL};
-        valid                = new String[] {"0", "1234", "1,234", "1,234.5", "1234X", LONG_MAX, LONG_MIN, LONG_MAX_0, LONG_MIN_0};
-        validCompare         = new Number[] {testZero, testNumber, testNumber, testNumber, testNumber, LONG_MAX_VAL, LONG_MIN_VAL, LONG_MAX_VAL, LONG_MIN_VAL};
+        testNumber = Long.valueOf(1234);
+        testZero = Long.valueOf(0);
+        validStrict = new String[] { "0", "1234", "1,234", LONG_MAX, LONG_MIN };
+        validStrictCompare = new Number[] { testZero, testNumber, testNumber, LONG_MAX_VAL, LONG_MIN_VAL };
+        valid = new String[] { "0", "1234", "1,234", "1,234.5", "1234X", LONG_MAX, LONG_MIN, LONG_MAX_0, LONG_MIN_0 };
+        validCompare = new Number[] { testZero, testNumber, testNumber, testNumber, testNumber, LONG_MAX_VAL, LONG_MIN_VAL, LONG_MAX_VAL, LONG_MIN_VAL };
 
         testStringUS = "1,234";
         testStringDE = "1.234";
@@ -77,50 +78,18 @@
         // Localized Pattern test
         localeValue = testStringDE;
         localePattern = "#.###";
-        testLocale    = Locale.GERMANY;
+        testLocale = Locale.GERMANY;
         localeExpected = testNumber;
 
     }
 
     /**
-     * Test LongValidator validate Methods
-     */
-    public void testLongValidatorMethods() {
-        final Locale locale     = Locale.GERMAN;
-        final String pattern    = "0,00,00";
-        final String patternVal = "1,23,45";
-        final String germanPatternVal = "1.23.45";
-        final String localeVal  = "12.345";
-        final String defaultVal = "12,345";
-        final String XXXX    = "XXXX";
-        final Long expected = Long.valueOf(12345);
-        assertEquals("validate(A) default", expected, LongValidator.getInstance().validate(defaultVal));
-        assertEquals("validate(A) locale ", expected, LongValidator.getInstance().validate(localeVal, locale));
-        assertEquals("validate(A) pattern", expected, LongValidator.getInstance().validate(patternVal, pattern));
-        assertEquals("validate(A) both",    expected, LongValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertTrue("isValid(A) default", LongValidator.getInstance().isValid(defaultVal));
-        assertTrue("isValid(A) locale ", LongValidator.getInstance().isValid(localeVal, locale));
-        assertTrue("isValid(A) pattern", LongValidator.getInstance().isValid(patternVal, pattern));
-        assertTrue("isValid(A) both",    LongValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertNull("validate(B) default", LongValidator.getInstance().validate(XXXX));
-        assertNull("validate(B) locale ", LongValidator.getInstance().validate(XXXX, locale));
-        assertNull("validate(B) pattern", LongValidator.getInstance().validate(XXXX, pattern));
-        assertNull("validate(B) both",    LongValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN));
-
-        assertFalse("isValid(B) default", LongValidator.getInstance().isValid(XXXX));
-        assertFalse("isValid(B) locale ", LongValidator.getInstance().isValid(XXXX, locale));
-        assertFalse("isValid(B) pattern", LongValidator.getInstance().isValid(XXXX, pattern));
-        assertFalse("isValid(B) both",    LongValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN));
-    }
-
-    /**
      * Test Long Range/Min/Max
      */
+    @Test
     public void testLongRangeMinMax() {
-        final LongValidator validator = (LongValidator)strictValidator;
-        final Long number9  = validator.validate("9", "#");
+        final LongValidator validator = (LongValidator) strictValidator;
+        final Long number9 = validator.validate("9", "#");
         final Long number10 = validator.validate("10", "#");
         final Long number11 = validator.validate("11", "#");
         final Long number19 = validator.validate("19", "#");
@@ -128,20 +97,54 @@
         final Long number21 = validator.validate("21", "#");
 
         // Test isInRange()
-        assertFalse("isInRange() < min",   validator.isInRange(number9,  10, 20));
-        assertTrue("isInRange() = min",    validator.isInRange(number10, 10, 20));
-        assertTrue("isInRange() in range", validator.isInRange(number11, 10, 20));
-        assertTrue("isInRange() = max",    validator.isInRange(number20, 10, 20));
-        assertFalse("isInRange() > max",   validator.isInRange(number21, 10, 20));
+        assertFalse(validator.isInRange(number9, 10, 20), "isInRange() < min");
+        assertTrue(validator.isInRange(number10, 10, 20), "isInRange() = min");
+        assertTrue(validator.isInRange(number11, 10, 20), "isInRange() in range");
+        assertTrue(validator.isInRange(number20, 10, 20), "isInRange() = max");
+        assertFalse(validator.isInRange(number21, 10, 20), "isInRange() > max");
 
         // Test minValue()
-        assertFalse("minValue() < min",    validator.minValue(number9,  10));
-        assertTrue("minValue() = min",     validator.minValue(number10, 10));
-        assertTrue("minValue() > min",     validator.minValue(number11, 10));
+        assertFalse(validator.minValue(number9, 10), "minValue() < min");
+        assertTrue(validator.minValue(number10, 10), "minValue() = min");
+        assertTrue(validator.minValue(number11, 10), "minValue() > min");
 
         // Test minValue()
-        assertTrue("maxValue() < max",     validator.maxValue(number19, 20));
-        assertTrue("maxValue() = max",     validator.maxValue(number20, 20));
-        assertFalse("maxValue() > max",    validator.maxValue(number21, 20));
+        assertTrue(validator.maxValue(number19, 20), "maxValue() < max");
+        assertTrue(validator.maxValue(number20, 20), "maxValue() = max");
+        assertFalse(validator.maxValue(number21, 20), "maxValue() > max");
+    }
+
+    /**
+     * Test LongValidator validate Methods
+     */
+    @Test
+    public void testLongValidatorMethods() {
+        final Locale locale = Locale.GERMAN;
+        final String pattern = "0,00,00";
+        final String patternVal = "1,23,45";
+        final String germanPatternVal = "1.23.45";
+        final String localeVal = "12.345";
+        final String defaultVal = "12,345";
+        final String XXXX = "XXXX";
+        final Long expected = Long.valueOf(12345);
+        assertEquals(expected, LongValidator.getInstance().validate(defaultVal), "validate(A) default");
+        assertEquals(expected, LongValidator.getInstance().validate(localeVal, locale), "validate(A) locale");
+        assertEquals(expected, LongValidator.getInstance().validate(patternVal, pattern), "validate(A) pattern");
+        assertEquals(expected, LongValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN), "validate(A) both");
+
+        assertTrue(LongValidator.getInstance().isValid(defaultVal), "isValid(A) default");
+        assertTrue(LongValidator.getInstance().isValid(localeVal, locale), "isValid(A) locale");
+        assertTrue(LongValidator.getInstance().isValid(patternVal, pattern), "isValid(A) pattern");
+        assertTrue(LongValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN), "isValid(A) both");
+
+        assertNull(LongValidator.getInstance().validate(XXXX), "validate(B) default");
+        assertNull(LongValidator.getInstance().validate(XXXX, locale), "validate(B) locale");
+        assertNull(LongValidator.getInstance().validate(XXXX, pattern), "validate(B) pattern");
+        assertNull(LongValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN), "validate(B) both");
+
+        assertFalse(LongValidator.getInstance().isValid(XXXX), "isValid(B) default");
+        assertFalse(LongValidator.getInstance().isValid(XXXX, locale), "isValid(B) locale");
+        assertFalse(LongValidator.getInstance().isValid(XXXX, pattern), "isValid(B) pattern");
+        assertFalse(LongValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN), "isValid(B) both");
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/PercentValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/PercentValidatorTest.java
index 01239c2..7524881 100644
--- a/src/test/java/org/apache/commons/validator/routines/PercentValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/PercentValidatorTest.java
@@ -16,52 +16,72 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+
 import java.math.BigDecimal;
 import java.util.Locale;
 
-import junit.framework.TestCase;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Test Case for PercentValidator.
  */
-public class PercentValidatorTest extends TestCase {
+public class PercentValidatorTest {
 
     protected PercentValidator validator;
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public PercentValidatorTest(final String name) {
-        super(name);
-    }
-
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         validator = new PercentValidator();
     }
 
     /**
      * Tear down
-     * @throws Exception
      */
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
+    @AfterEach
+    protected void tearDown() {
         validator = null;
     }
 
     /**
      * Test Format Type
      */
+    @Test
     public void testFormatType() {
-        assertEquals("Format Type A", 2, PercentValidator.getInstance().getFormatType());
-        assertEquals("Format Type B", AbstractNumberValidator.PERCENT_FORMAT, PercentValidator.getInstance().getFormatType());
+        assertEquals(2, PercentValidator.getInstance().getFormatType(), "Format Type A");
+        assertEquals(AbstractNumberValidator.PERCENT_FORMAT, PercentValidator.getInstance().getFormatType(), "Format Type B");
+    }
+
+    /**
+     * Test Invalid percentage values
+     */
+    @Test
+    public void testInvalid() {
+        final BigDecimalValidator validator = PercentValidator.getInstance();
+
+        // Invalid Missing
+        assertFalse(validator.isValid(null), "isValid() Null Value");
+        assertFalse(validator.isValid(""), "isValid() Empty Value");
+        assertNull(validator.validate(null), "validate() Null Value");
+        assertNull(validator.validate(""), "validate() Empty Value");
+
+        // Invalid UK
+        assertFalse(validator.isValid("12@", Locale.UK), "UK wrong symbol"); // ???
+        assertFalse(validator.isValid("(12%)", Locale.UK), "UK wrong negative");
+
+        // Invalid US - can't find a Locale with different symbols!
+        assertFalse(validator.isValid("12@", Locale.US), "US wrong symbol"); // ???
+        assertFalse(validator.isValid("(12%)", Locale.US), "US wrong negative");
     }
 
     /**
      * Test Valid percentage values
      */
+    @Test
     public void testValid() {
         // Set the default Locale
         final Locale origDefault = Locale.getDefault();
@@ -70,46 +90,25 @@
         final BigDecimalValidator validator = PercentValidator.getInstance();
         final BigDecimal expected = new BigDecimal("0.12");
         final BigDecimal negative = new BigDecimal("-0.12");
-        final BigDecimal hundred  = new BigDecimal("1.00");
+        final BigDecimal hundred = new BigDecimal("1.00");
 
-        assertEquals("Default locale", expected, validator.validate("12%"));
-        assertEquals("Default negtve", negative, validator.validate("-12%"));
+        assertEquals(expected, validator.validate("12%"), "Default locale");
+        assertEquals(negative, validator.validate("-12%"), "Default negtve");
 
         // Invalid UK
-        assertEquals("UK locale",      expected, validator.validate("12%",   Locale.UK));
-        assertEquals("UK negative",    negative, validator.validate("-12%",  Locale.UK));
-        assertEquals("UK No symbol",   expected, validator.validate("12",    Locale.UK));
+        assertEquals(expected, validator.validate("12%", Locale.UK), "UK locale");
+        assertEquals(negative, validator.validate("-12%", Locale.UK), "UK negative");
+        assertEquals(expected, validator.validate("12", Locale.UK), "UK No symbol");
 
         // Invalid US - can't find a Locale with different symbols!
-        assertEquals("US locale",      expected, validator.validate("12%",   Locale.US));
-        assertEquals("US negative",    negative, validator.validate("-12%",  Locale.US));
-        assertEquals("US No symbol",   expected, validator.validate("12",    Locale.US));
+        assertEquals(expected, validator.validate("12%", Locale.US), "US locale");
+        assertEquals(negative, validator.validate("-12%", Locale.US), "US negative");
+        assertEquals(expected, validator.validate("12", Locale.US), "US No symbol");
 
-        assertEquals("100%",           hundred, validator.validate("100%"));
+        assertEquals(hundred, validator.validate("100%"), "100%");
 
         // Restore the original default
         Locale.setDefault(origDefault);
     }
 
-    /**
-     * Test Invalid percentage values
-     */
-    public void testInvalid() {
-        final BigDecimalValidator validator = PercentValidator.getInstance();
-
-        // Invalid Missing
-        assertFalse("isValid() Null Value",    validator.isValid(null));
-        assertFalse("isValid() Empty Value",   validator.isValid(""));
-        assertNull("validate() Null Value",    validator.validate(null));
-        assertNull("validate() Empty Value",   validator.validate(""));
-
-        // Invalid UK
-        assertFalse("UK wrong symbol",    validator.isValid("12@",   Locale.UK)); // ???
-        assertFalse("UK wrong negative",  validator.isValid("(12%)", Locale.UK));
-
-        // Invalid US - can't find a Locale with different symbols!
-        assertFalse("US wrong symbol",    validator.isValid("12@",   Locale.US)); // ???
-        assertFalse("US wrong negative",  validator.isValid("(12%)", Locale.US));
-    }
-
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/RegexValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/RegexValidatorTest.java
index 85c398f..be773ee 100644
--- a/src/test/java/org/apache/commons/validator/routines/RegexValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/RegexValidatorTest.java
@@ -16,41 +16,39 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.util.regex.Pattern;
 import java.util.regex.PatternSyntaxException;
 
-import junit.framework.TestCase;
+import org.junit.jupiter.api.Test;
 
 /**
  * Test Case for RegexValidatorTest.
- *
- * @since 1.4
  */
-public class RegexValidatorTest extends TestCase {
+public class RegexValidatorTest {
 
-    private static final String REGEX         = "^([abc]*)(?:\\-)([DEF]*)(?:\\-)([123]*)$";
+    private static final String REGEX = "^([abc]*)(?:\\-)([DEF]*)(?:\\-)([123]*)$";
 
     private static final String COMPONENT_1 = "([abc]{3})";
     private static final String COMPONENT_2 = "([DEF]{3})";
     private static final String COMPONENT_3 = "([123]{3})";
-    private static final String SEPARATOR_1  = "(?:\\-)";
-    private static final String SEPARATOR_2  = "(?:\\s)";
+    private static final String SEPARATOR_1 = "(?:\\-)";
+    private static final String SEPARATOR_2 = "(?:\\s)";
     private static final String REGEX_1 = "^" + COMPONENT_1 + SEPARATOR_1 + COMPONENT_2 + SEPARATOR_1 + COMPONENT_3 + "$";
     private static final String REGEX_2 = "^" + COMPONENT_1 + SEPARATOR_2 + COMPONENT_2 + SEPARATOR_2 + COMPONENT_3 + "$";
     private static final String REGEX_3 = "^" + COMPONENT_1 + COMPONENT_2 + COMPONENT_3 + "$";
-    private static final String[] MULTIPLE_REGEX = {REGEX_1, REGEX_2, REGEX_3};
-
-    /**
-     * Constrct a new test case.
-     * @param name The name of the test
-     */
-    public RegexValidatorTest(final String name) {
-        super(name);
-    }
+    private static final String[] MULTIPLE_REGEX = { REGEX_1, REGEX_2, REGEX_3 };
 
     /**
      * Compare two arrays
-     * @param label Label for the test
+     *
+     * @param label  Label for the test
      * @param expect Expected array
      * @param result Actual array
      */
@@ -72,29 +70,14 @@
 
         // Check Values
         for (int i = 0; i < expect.length; i++) {
-            assertEquals(label +" value[" + i + "]", expect[i], result[i]);
+            assertEquals(expect[i], result[i], label + " value[" + i + "]");
         }
     }
 
     /**
-     * Set Up.
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-    }
-
-    /**
-     * Tear Down.
-     */
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
-    }
-
-    /**
      * Test exceptions
      */
+    @Test
     public void testExceptions() {
         final String invalidRegex = "^([abCD12]*$";
         try {
@@ -104,6 +87,7 @@
         }
     }
 
+    @Test
     public void testGetPatterns() {
         final RegexValidator regexValidator = new RegexValidator(MULTIPLE_REGEX);
         assertNotSame(regexValidator.getPatterns(), regexValidator.getPatterns());
@@ -116,6 +100,7 @@
     /**
      * Test exceptions
      */
+    @Test
     public void testMissingRegex() {
 
         // Single Regular Expression - null
@@ -123,7 +108,7 @@
             new RegexValidator((String) null);
             fail("Single Null - expected IllegalArgumentException");
         } catch (final IllegalArgumentException e) {
-            assertEquals("Single Null", "Regular expression[0] is missing", e.getMessage());
+            assertEquals(e.getMessage(), "Regular expression[0] is missing", "Single Null");
         }
 
         // Single Regular Expression - Zero Length
@@ -131,7 +116,7 @@
             new RegexValidator("");
             fail("Single Zero Length - expected IllegalArgumentException");
         } catch (final IllegalArgumentException e) {
-            assertEquals("Single Zero Length", "Regular expression[0] is missing", e.getMessage());
+            assertEquals(e.getMessage(), "Regular expression[0] is missing", "Single Zero Length");
         }
 
         // Multiple Regular Expression - Null array
@@ -139,15 +124,15 @@
             new RegexValidator((String[]) null);
             fail("Null Array - expected IllegalArgumentException");
         } catch (final IllegalArgumentException e) {
-            assertEquals("Null Array", "Regular expressions are missing", e.getMessage());
+            assertEquals(e.getMessage(), "Regular expressions are missing", "Null Array");
         }
 
         // Multiple Regular Expression - Zero Length array
         try {
-            new RegexValidator(new String[0]);
+            new RegexValidator();
             fail("Zero Length Array - expected IllegalArgumentException");
         } catch (final IllegalArgumentException e) {
-            assertEquals("Zero Length Array", "Regular expressions are missing", e.getMessage());
+            assertEquals(e.getMessage(), "Regular expressions are missing", "Zero Length Array");
         }
 
         // Multiple Regular Expression - Array has Null
@@ -156,7 +141,7 @@
             new RegexValidator(expressions);
             fail("Array has Null - expected IllegalArgumentException");
         } catch (final IllegalArgumentException e) {
-            assertEquals("Array has Null", "Regular expression[1] is missing", e.getMessage());
+            assertEquals(e.getMessage(), "Regular expression[1] is missing", "Array has Null");
         }
 
         // Multiple Regular Expression - Array has Zero Length
@@ -165,140 +150,145 @@
             new RegexValidator(expressions);
             fail("Array has Zero Length - expected IllegalArgumentException");
         } catch (final IllegalArgumentException e) {
-            assertEquals("Array has Zero Length", "Regular expression[0] is missing", e.getMessage());
+            assertEquals(e.getMessage(), "Regular expression[0] is missing", "Array has Zero Length");
         }
     }
-    
+
     /**
      * Test with multiple regular expressions (case in-sensitive).
      */
+    @Test
     public void testMultipleInsensitive() {
 
-        // ------------ Set up In-sensitive Validators
+        // Set up In-sensitive Validators
         final RegexValidator multiple = new RegexValidator(MULTIPLE_REGEX, false);
-        final RegexValidator single1   = new RegexValidator(REGEX_1, false);
-        final RegexValidator single2   = new RegexValidator(REGEX_2, false);
-        final RegexValidator single3   = new RegexValidator(REGEX_3, false);
+        final RegexValidator single1 = new RegexValidator(REGEX_1, false);
+        final RegexValidator single2 = new RegexValidator(REGEX_2, false);
+        final RegexValidator single3 = new RegexValidator(REGEX_3, false);
 
-        // ------------ Set up test values
+        // Set up test values
         String value = "AAC FDE 321";
         final String expect = "AACFDE321";
-        final String[] array = {"AAC", "FDE", "321"};
+        final String[] array = { "AAC", "FDE", "321" };
 
         // isValid()
-        assertEquals("isValid() Multiple", true,  multiple.isValid(value));
-        assertEquals("isValid() 1st",      false, single1.isValid(value));
-        assertEquals("isValid() 2nd",      true,  single2.isValid(value));
-        assertEquals("isValid() 3rd",      false, single3.isValid(value));
+        assertTrue(multiple.isValid(value), "isValid() Multiple");
+        assertFalse(single1.isValid(value), "isValid() 1st");
+        assertTrue(single2.isValid(value), "isValid() 2nd");
+        assertFalse(single3.isValid(value), "isValid() 3rd");
 
         // validate()
-        assertEquals("validate() Multiple", expect, multiple.validate(value));
-        assertEquals("validate() 1st",      null,   single1.validate(value));
-        assertEquals("validate() 2nd",      expect, single2.validate(value));
-        assertEquals("validate() 3rd",      null,   single3.validate(value));
+        assertEquals(expect, multiple.validate(value), "validate() Multiple");
+        assertNull(single1.validate(value), "validate() 1st");
+        assertEquals(expect, single2.validate(value), "validate() 2nd");
+        assertNull(single3.validate(value), "validate() 3rd");
 
         // match()
         checkArray("match() Multiple", array, multiple.match(value));
-        checkArray("match() 1st",      null,  single1.match(value));
-        checkArray("match() 2nd",      array, single2.match(value));
-        checkArray("match() 3rd",      null,  single3.match(value));
+        checkArray("match() 1st", null, single1.match(value));
+        checkArray("match() 2nd", array, single2.match(value));
+        checkArray("match() 3rd", null, single3.match(value));
 
         // All invalid
         value = "AAC*FDE*321";
-        assertEquals("isValid() Invalid",  false, multiple.isValid(value));
-        assertEquals("validate() Invalid", null,  multiple.validate(value));
-        assertEquals("match() Multiple",   null,  multiple.match(value));
+        assertFalse(multiple.isValid(value), "isValid() Invalid");
+        assertNull(multiple.validate(value), "validate() Invalid");
+        assertNull(multiple.match(value), "match() Multiple");
     }
 
     /**
      * Test with multiple regular expressions (case sensitive).
      */
+    @Test
     public void testMultipleSensitive() {
 
-        // ------------ Set up Sensitive Validators
-        final RegexValidator multiple   = new RegexValidator(MULTIPLE_REGEX);
-        final RegexValidator single1   = new RegexValidator(REGEX_1);
-        final RegexValidator single2   = new RegexValidator(REGEX_2);
-        final RegexValidator single3   = new RegexValidator(REGEX_3);
+        // Set up Sensitive Validators
+        final RegexValidator multiple = new RegexValidator(MULTIPLE_REGEX);
+        final RegexValidator single1 = new RegexValidator(REGEX_1);
+        final RegexValidator single2 = new RegexValidator(REGEX_2);
+        final RegexValidator single3 = new RegexValidator(REGEX_3);
 
-        // ------------ Set up test values
+        // Set up test values
         String value = "aac FDE 321";
         final String expect = "aacFDE321";
-        final String[] array = {"aac", "FDE", "321"};
+        final String[] array = { "aac", "FDE", "321" };
 
         // isValid()
-        assertEquals("Sensitive isValid() Multiple", true,  multiple.isValid(value));
-        assertEquals("Sensitive isValid() 1st",      false, single1.isValid(value));
-        assertEquals("Sensitive isValid() 2nd",      true,  single2.isValid(value));
-        assertEquals("Sensitive isValid() 3rd",      false, single3.isValid(value));
+        assertTrue( multiple.isValid(value), "Sensitive isValid() Multiple");
+        assertFalse(single1.isValid(value), "Sensitive isValid() 1st");
+        assertTrue( single2.isValid(value), "Sensitive isValid() 2nd");
+        assertFalse(single3.isValid(value), "Sensitive isValid() 3rd");
 
         // validate()
-        assertEquals("Sensitive validate() Multiple", expect, multiple.validate(value));
-        assertEquals("Sensitive validate() 1st",      null,   single1.validate(value));
-        assertEquals("Sensitive validate() 2nd",      expect, single2.validate(value));
-        assertEquals("Sensitive validate() 3rd",      null,   single3.validate(value));
+        assertEquals(expect, multiple.validate(value), "Sensitive validate() Multiple");
+        assertNull(single1.validate(value), "Sensitive validate() 1st");
+        assertEquals(expect, single2.validate(value), "Sensitive validate() 2nd");
+        assertNull(single3.validate(value), "Sensitive validate() 3rd");
 
         // match()
         checkArray("Sensitive match() Multiple", array, multiple.match(value));
-        checkArray("Sensitive match() 1st",      null,  single1.match(value));
-        checkArray("Sensitive match() 2nd",      array, single2.match(value));
-        checkArray("Sensitive match() 3rd",      null,  single3.match(value));
+        checkArray("Sensitive match() 1st", null, single1.match(value));
+        checkArray("Sensitive match() 2nd", array, single2.match(value));
+        checkArray("Sensitive match() 3rd", null, single3.match(value));
 
         // All invalid
         value = "AAC*FDE*321";
-        assertEquals("isValid() Invalid",  false, multiple.isValid(value));
-        assertEquals("validate() Invalid", null,  multiple.validate(value));
-        assertEquals("match() Multiple",   null,  multiple.match(value));
+        assertFalse(multiple.isValid(value), "isValid() Invalid");
+        assertNull(multiple.validate(value), "validate() Invalid");
+        assertNull(multiple.match(value), "match() Multiple");
     }
 
     /**
      * Test Null value
      */
+    @Test
     public void testNullValue() {
 
         final RegexValidator validator = new RegexValidator(REGEX);
-        assertEquals("Instance isValid()",  false, validator.isValid(null));
-        assertEquals("Instance validate()", null,  validator.validate(null));
-        assertEquals("Instance match()",    null,  validator.match(null));
+        assertFalse(validator.isValid(null), "Instance isValid()");
+        assertNull(validator.validate(null), "Instance validate()");
+        assertNull(validator.match(null), "Instance match()");
     }
 
     /**
      * Test instance methods with single regular expression.
      */
+    @Test
     public void testSingle() {
-        final RegexValidator sensitive   = new RegexValidator(REGEX);
+        final RegexValidator sensitive = new RegexValidator(REGEX);
         final RegexValidator insensitive = new RegexValidator(REGEX, false);
 
         // isValid()
-        assertEquals("Sensitive isValid() valid",     true,   sensitive.isValid("ac-DE-1"));
-        assertEquals("Sensitive isValid() invalid",   false,  sensitive.isValid("AB-de-1"));
-        assertEquals("Insensitive isValid() valid",   true,   insensitive.isValid("AB-de-1"));
-        assertEquals("Insensitive isValid() invalid", false,  insensitive.isValid("ABd-de-1"));
+        assertTrue( sensitive.isValid("ac-DE-1"), "Sensitive isValid() valid");
+        assertFalse(sensitive.isValid("AB-de-1"), "Sensitive isValid() invalid");
+        assertTrue( insensitive.isValid("AB-de-1"), "Insensitive isValid() valid");
+        assertFalse(insensitive.isValid("ABd-de-1"), "Insensitive isValid() invalid");
 
         // validate()
-        assertEquals("Sensitive validate() valid",     "acDE1", sensitive.validate("ac-DE-1"));
-        assertEquals("Sensitive validate() invalid",   null,    sensitive.validate("AB-de-1"));
-        assertEquals("Insensitive validate() valid",   "ABde1", insensitive.validate("AB-de-1"));
-        assertEquals("Insensitive validate() invalid", null,    insensitive.validate("ABd-de-1"));
+        assertEquals(sensitive.validate("ac-DE-1"), "acDE1", "Sensitive validate() valid");
+        assertNull(sensitive.validate("AB-de-1"), "Sensitive validate() invalid");
+        assertEquals(insensitive.validate("AB-de-1"), "ABde1", "Insensitive validate() valid");
+        assertNull(insensitive.validate("ABd-de-1"), "Insensitive validate() invalid");
 
         // match()
-        checkArray("Sensitive match() valid",     new String[] {"ac", "DE", "1"}, sensitive.match("ac-DE-1"));
-        checkArray("Sensitive match() invalid",   null,                           sensitive.match("AB-de-1"));
-        checkArray("Insensitive match() valid",   new String[] {"AB", "de", "1"}, insensitive.match("AB-de-1"));
-        checkArray("Insensitive match() invalid", null,                           insensitive.match("ABd-de-1"));
-        assertEquals("validate one", "ABC", (new RegexValidator("^([A-Z]*)$")).validate("ABC"));
-        checkArray("match one", new String[] {"ABC"}, (new RegexValidator("^([A-Z]*)$")).match("ABC"));
+        checkArray("Sensitive match() valid", new String[] { "ac", "DE", "1" }, sensitive.match("ac-DE-1"));
+        checkArray("Sensitive match() invalid", null, sensitive.match("AB-de-1"));
+        checkArray("Insensitive match() valid", new String[] { "AB", "de", "1" }, insensitive.match("AB-de-1"));
+        checkArray("Insensitive match() invalid", null, insensitive.match("ABd-de-1"));
+        assertEquals(new RegexValidator("^([A-Z]*)$").validate("ABC"), "ABC", "validate one");
+        checkArray("match one", new String[] { "ABC" }, new RegexValidator("^([A-Z]*)$").match("ABC"));
     }
 
     /**
      * Test toString() method
      */
+    @Test
     public void testToString() {
         final RegexValidator single = new RegexValidator(REGEX);
-        assertEquals("Single", "RegexValidator{" + REGEX + "}", single.toString());
+        assertEquals(single.toString(), "RegexValidator{" + REGEX + "}", "Single");
 
-        final RegexValidator multiple = new RegexValidator(new String[] {REGEX, REGEX});
-        assertEquals("Multiple", "RegexValidator{" + REGEX + "," + REGEX + "}", multiple.toString());
+        final RegexValidator multiple = new RegexValidator(REGEX, REGEX);
+        assertEquals(multiple.toString(), "RegexValidator{" + REGEX + "," + REGEX + "}", "Multiple");
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/ShortValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/ShortValidatorTest.java
index a7327a0..393d193 100644
--- a/src/test/java/org/apache/commons/validator/routines/ShortValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/ShortValidatorTest.java
@@ -16,26 +16,27 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.util.Locale;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Test Case for ShortValidator.
  */
 public class ShortValidatorTest extends AbstractNumberValidatorTest {
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public ShortValidatorTest(final String name) {
-        super(name);
-    }
-
     @Override
-    protected void setUp() throws Exception {
+    @BeforeEach
+    protected void setUp() {
         super.setUp();
 
-        validator       = new ShortValidator(false, 0);
+        validator = new ShortValidator(false, 0);
         strictValidator = new ShortValidator();
 
         testPattern = "#,###";
@@ -47,18 +48,18 @@
         minMinusOne = Long.valueOf(min.longValue() - 1);
 
         // testInvalidStrict()
-        invalidStrict = new String[] {null, "", "X", "X12", "12X", "1X2", "1.2"};
+        invalidStrict = new String[] { null, "", "X", "X12", "12X", "1X2", "1.2" };
 
         // testInvalidNotStrict()
-        invalid       = new String[] {null, "", "X", "X12"};
+        invalid = new String[] { null, "", "X", "X12" };
 
         // testValid()
-        testNumber    = Short.valueOf((short)1234);
-        testZero      = Short.valueOf((short)0);
-        validStrict          = new String[] {"0", "1234", "1,234"};
-        validStrictCompare   = new Number[] {testZero, testNumber, testNumber};
-        valid                = new String[] {"0", "1234", "1,234", "1,234.5", "1234X"};
-        validCompare         = new Number[] {testZero, testNumber, testNumber, testNumber, testNumber};
+        testNumber = Short.valueOf((short) 1234);
+        testZero = Short.valueOf((short) 0);
+        validStrict = new String[] { "0", "1234", "1,234" };
+        validStrictCompare = new Number[] { testZero, testNumber, testNumber };
+        valid = new String[] { "0", "1234", "1,234", "1,234.5", "1234X" };
+        validCompare = new Number[] { testZero, testNumber, testNumber, testNumber, testNumber };
 
         testStringUS = "1,234";
         testStringDE = "1.234";
@@ -66,73 +67,75 @@
         // Localized Pattern test
         localeValue = testStringDE;
         localePattern = "#.###";
-        testLocale    = Locale.GERMANY;
+        testLocale = Locale.GERMANY;
         localeExpected = testNumber;
 
     }
 
     /**
-     * Test ShortValidator validate Methods
-     */
-    public void testShortValidatorMethods() {
-        final Locale locale     = Locale.GERMAN;
-        final String pattern    = "0,00,00";
-        final String patternVal = "1,23,45";
-        final String germanPatternVal = "1.23.45";
-        final String localeVal  = "12.345";
-        final String defaultVal = "12,345";
-        final String XXXX    = "XXXX";
-        final Short expected = Short.valueOf((short)12345);
-        assertEquals("validate(A) default", expected, ShortValidator.getInstance().validate(defaultVal));
-        assertEquals("validate(A) locale ", expected, ShortValidator.getInstance().validate(localeVal, locale));
-        assertEquals("validate(A) pattern", expected, ShortValidator.getInstance().validate(patternVal, pattern));
-        assertEquals("validate(A) both",    expected, ShortValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertTrue("isValid(A) default", ShortValidator.getInstance().isValid(defaultVal));
-        assertTrue("isValid(A) locale ", ShortValidator.getInstance().isValid(localeVal, locale));
-        assertTrue("isValid(A) pattern", ShortValidator.getInstance().isValid(patternVal, pattern));
-        assertTrue("isValid(A) both",    ShortValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN));
-
-        assertNull("validate(B) default", ShortValidator.getInstance().validate(XXXX));
-        assertNull("validate(B) locale ", ShortValidator.getInstance().validate(XXXX, locale));
-        assertNull("validate(B) pattern", ShortValidator.getInstance().validate(XXXX, pattern));
-        assertNull("validate(B) both",    ShortValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN));
-
-        assertFalse("isValid(B) default", ShortValidator.getInstance().isValid(XXXX));
-        assertFalse("isValid(B) locale ", ShortValidator.getInstance().isValid(XXXX, locale));
-        assertFalse("isValid(B) pattern", ShortValidator.getInstance().isValid(XXXX, pattern));
-        assertFalse("isValid(B) both",    ShortValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN));
-    }
-
-    /**
      * Test Short Range/Min/Max
      */
+    @Test
     public void testShortRangeMinMax() {
-        final ShortValidator validator = (ShortValidator)strictValidator;
-        final Short number9  = validator.validate("9", "#");
+        final ShortValidator validator = (ShortValidator) strictValidator;
+        final Short number9 = validator.validate("9", "#");
         final Short number10 = validator.validate("10", "#");
         final Short number11 = validator.validate("11", "#");
         final Short number19 = validator.validate("19", "#");
         final Short number20 = validator.validate("20", "#");
         final Short number21 = validator.validate("21", "#");
-        final short min = (short)10;
-        final short max = (short)20;
+        final short min = (short) 10;
+        final short max = (short) 20;
 
         // Test isInRange()
-        assertFalse("isInRange() < min",   validator.isInRange(number9,  min, max));
-        assertTrue("isInRange() = min",    validator.isInRange(number10, min, max));
-        assertTrue("isInRange() in range", validator.isInRange(number11, min, max));
-        assertTrue("isInRange() = max",    validator.isInRange(number20, min, max));
-        assertFalse("isInRange() > max",   validator.isInRange(number21, min, max));
+        assertFalse(validator.isInRange(number9, min, max), "isInRange() < min");
+        assertTrue(validator.isInRange(number10, min, max), "isInRange() = min");
+        assertTrue(validator.isInRange(number11, min, max), "isInRange() in range");
+        assertTrue(validator.isInRange(number20, min, max), "isInRange() = max");
+        assertFalse(validator.isInRange(number21, min, max), "isInRange() > max");
 
         // Test minValue()
-        assertFalse("minValue() < min",    validator.minValue(number9,  min));
-        assertTrue("minValue() = min",     validator.minValue(number10, min));
-        assertTrue("minValue() > min",     validator.minValue(number11, min));
+        assertFalse(validator.minValue(number9, min), "minValue() < min");
+        assertTrue(validator.minValue(number10, min), "minValue() = min");
+        assertTrue(validator.minValue(number11, min), "minValue() > min");
 
         // Test minValue()
-        assertTrue("maxValue() < max",     validator.maxValue(number19, max));
-        assertTrue("maxValue() = max",     validator.maxValue(number20, max));
-        assertFalse("maxValue() > max",    validator.maxValue(number21, max));
+        assertTrue(validator.maxValue(number19, max), "maxValue() < max");
+        assertTrue(validator.maxValue(number20, max), "maxValue() = max");
+        assertFalse(validator.maxValue(number21, max), "maxValue() > max");
+    }
+
+    /**
+     * Test ShortValidator validate Methods
+     */
+    @Test
+    public void testShortValidatorMethods() {
+        final Locale locale = Locale.GERMAN;
+        final String pattern = "0,00,00";
+        final String patternVal = "1,23,45";
+        final String germanPatternVal = "1.23.45";
+        final String localeVal = "12.345";
+        final String defaultVal = "12,345";
+        final String XXXX = "XXXX";
+        final Short expected = Short.valueOf((short) 12345);
+        assertEquals(expected, ShortValidator.getInstance().validate(defaultVal), "validate(A) default");
+        assertEquals(expected, ShortValidator.getInstance().validate(localeVal, locale), "validate(A) locale");
+        assertEquals(expected, ShortValidator.getInstance().validate(patternVal, pattern), "validate(A) pattern");
+        assertEquals(expected, ShortValidator.getInstance().validate(germanPatternVal, pattern, Locale.GERMAN), "validate(A) both");
+
+        assertTrue(ShortValidator.getInstance().isValid(defaultVal), "isValid(A) default");
+        assertTrue(ShortValidator.getInstance().isValid(localeVal, locale), "isValid(A) locale");
+        assertTrue(ShortValidator.getInstance().isValid(patternVal, pattern), "isValid(A) pattern");
+        assertTrue(ShortValidator.getInstance().isValid(germanPatternVal, pattern, Locale.GERMAN), "isValid(A) both");
+
+        assertNull(ShortValidator.getInstance().validate(XXXX), "validate(B) default");
+        assertNull(ShortValidator.getInstance().validate(XXXX, locale), "validate(B) locale");
+        assertNull(ShortValidator.getInstance().validate(XXXX, pattern), "validate(B) pattern");
+        assertNull(ShortValidator.getInstance().validate(patternVal, pattern, Locale.GERMAN), "validate(B) both");
+
+        assertFalse(ShortValidator.getInstance().isValid(XXXX), "isValid(B) default");
+        assertFalse(ShortValidator.getInstance().isValid(XXXX, locale), "isValid(B) locale");
+        assertFalse(ShortValidator.getInstance().isValid(XXXX, pattern), "isValid(B) pattern");
+        assertFalse(ShortValidator.getInstance().isValid(patternVal, pattern, Locale.GERMAN), "isValid(B) both");
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/TimeValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/TimeValidatorTest.java
index d58c950..ce2e499 100644
--- a/src/test/java/org/apache/commons/validator/routines/TimeValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/TimeValidatorTest.java
@@ -16,96 +16,104 @@
  */
 package org.apache.commons.validator.routines;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
 import java.util.Calendar;
 import java.util.Date;
 import java.util.Locale;
 import java.util.TimeZone;
 
-import junit.framework.TestCase;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * Test Case for TimeValidator.
  */
-public class TimeValidatorTest extends TestCase {
+public class TimeValidatorTest {
 
     protected static final TimeZone GMT = TimeZone.getTimeZone("GMT"); // 0 offset
     protected static final TimeZone EST = TimeZone.getTimeZone("EST"); // - 5 hours
 
-    protected TimeValidator validator;
-
-    protected String[] patternValid = {
-                       "23-59-59"
-                      ,"00-00-00"
-                      ,"00-00-01"
-                      ,"0-0-0"
-                      ,"1-12-1"
-                      ,"10-49-18"
-                      ,"16-23-46"};
-    protected Date[] patternExpect = {
-                       createDate(null, 235959, 0)
-                      ,createDate(null, 0, 0)
-                      ,createDate(null, 1, 0)
-                      ,createDate(null, 0, 0)
-                      ,createDate(null, 11201, 0)
-                      ,createDate(null, 104918, 0)
-                      ,createDate(null, 162346, 0)};
-    protected String[] localeValid = {
-                      "23:59"
-                     ,"00:00"
-                     ,"00:01"
-                     ,"0:0"
-                     ,"1:12"
-                     ,"10:49"
-                     ,"16:23"};
-    protected Date[] localeExpect = {
-                      createDate(null, 235900, 0)
-                     ,createDate(null, 0, 0)
-                     ,createDate(null, 100, 0)
-                     ,createDate(null, 0, 0)
-                     ,createDate(null, 11200, 0)
-                     ,createDate(null, 104900, 0)
-                     ,createDate(null, 162300, 0)};
-    protected String[] patternInvalid = {
-                         "24-00-00"  // midnight
-                        ,"24-00-01"  // past midnight
-                        ,"25-02-03"  // invalid hour
-                        ,"10-61-31"  // invalid minute
-                        ,"10-01-61"  // invalid second
-                        ,"05:02-29"  // invalid sep
-                        ,"0X-01:01"  // invalid sep
-                        ,"05-0X-01"  // invalid char
-                        ,"10-01-0X"  // invalid char
-                        ,"01:01:05"  // invalid pattern
-                        ,"10-10"     // invalid pattern
-                        ,"10--10"    // invalid pattern
-                        ,"10-10-"};  // invalid pattern
-    protected String[] localeInvalid = {
-                         "24:00"  // midnight
-                        ,"24:00"  // past midnight
-                        ,"25:02"  // invalid hour
-                        ,"10:61"  // invalid minute
-                        ,"05-02"  // invalid sep
-                        ,"0X:01"  // invalid sep
-                        ,"05:0X"  // invalid char
-                        ,"01-01"  // invalid pattern
-                        ,"10:"     // invalid pattern
-                        ,"10::1"    // invalid pattern
-                        ,"10:1:"};  // invalid pattern
-
-    private Locale origDefault;
-    private TimeZone defaultZone;
-
     /**
-     * Constructor
-     * @param name test name
+     * Create a date instance for a specified time zone, date and time.
+     *
+     * @param zone        The time zone
+     * @param time        the time in HH:mm:ss format
+     * @param millisecond the milliseconds
+     * @return the new Date instance.
      */
-    public TimeValidatorTest(final String name) {
-        super(name);
+    protected static Date createDate(final TimeZone zone, final int time, final int millisecond) {
+        final Calendar calendar = createTime(zone, time, millisecond);
+        return calendar.getTime();
     }
 
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    /**
+     * Create a calendar instance for a specified time zone, date and time.
+     *
+     * @param zone        The time zone
+     * @param time        the time in HH:mm:ss format
+     * @param millisecond the milliseconds
+     * @return the new Calendar instance.
+     */
+    protected static Calendar createTime(final TimeZone zone, final int time, final int millisecond) {
+        final Calendar calendar = zone == null ? Calendar.getInstance() : Calendar.getInstance(zone);
+        final int hour = time / 10000 * 10000;
+        final int min = time / 100 * 100 - hour;
+        final int sec = time - (hour + min);
+        calendar.set(Calendar.YEAR, 1970);
+        calendar.set(Calendar.MONTH, 0);
+        calendar.set(Calendar.DATE, 1);
+        calendar.set(Calendar.HOUR_OF_DAY, hour / 10000);
+        calendar.set(Calendar.MINUTE, min / 100);
+        calendar.set(Calendar.SECOND, sec);
+        calendar.set(Calendar.MILLISECOND, millisecond);
+        return calendar;
+    }
+
+    protected TimeValidator validator;
+    protected String[] patternValid = { "23-59-59", "00-00-00", "00-00-01", "0-0-0", "1-12-1", "10-49-18", "16-23-46" };
+    protected Date[] patternExpect = { createDate(null, 235959, 0), createDate(null, 0, 0), createDate(null, 1, 0), createDate(null, 0, 0),
+            createDate(null, 11201, 0), createDate(null, 104918, 0), createDate(null, 162346, 0) };
+    protected String[] localeValid = { "23:59", "00:00", "00:01", "0:0", "1:12", "10:49", "16:23" };
+    protected Date[] localeExpect = { createDate(null, 235900, 0), createDate(null, 0, 0), createDate(null, 100, 0), createDate(null, 0, 0),
+            createDate(null, 11200, 0), createDate(null, 104900, 0), createDate(null, 162300, 0) };
+
+    protected String[] patternInvalid = { "24-00-00" // midnight
+            , "24-00-01" // past midnight
+            , "25-02-03" // invalid hour
+            , "10-61-31" // invalid minute
+            , "10-01-61" // invalid second
+            , "05:02-29" // invalid sep
+            , "0X-01:01" // invalid sep
+            , "05-0X-01" // invalid char
+            , "10-01-0X" // invalid char
+            , "01:01:05" // invalid pattern
+            , "10-10" // invalid pattern
+            , "10--10" // invalid pattern
+            , "10-10-" }; // invalid pattern
+    protected String[] localeInvalid = { "24:00" // midnight
+            , "24:00" // past midnight
+            , "25:02" // invalid hour
+            , "10:61" // invalid minute
+            , "05-02" // invalid sep
+            , "0X:01" // invalid sep
+            , "05:0X" // invalid char
+            , "01-01" // invalid pattern
+            , "10:" // invalid pattern
+            , "10::1" // invalid pattern
+            , "10:1:" }; // invalid pattern
+
+    private Locale origDefault;
+
+    private TimeZone defaultZone;
+
+    @BeforeEach
+    protected void setUp() {
         validator = new TimeValidator();
         defaultZone = TimeZone.getDefault();
         origDefault = Locale.getDefault();
@@ -113,71 +121,136 @@
 
     /**
      * Tear down
-     * @throws Exception
      */
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
+    @AfterEach
+    protected void tearDown() {
         validator = null;
         Locale.setDefault(origDefault);
         TimeZone.setDefault(defaultZone);
     }
 
     /**
-     * Test Valid Dates with "pattern" validation
+     * Test compare date methods
      */
-    public void testPatternValid() {
-        for (int i = 0; i < patternValid.length; i++) {
-            final String text = i + " value=[" +patternValid[i]+"] failed ";
-            final Calendar calendar = validator.validate(patternValid[i], "HH-mm-ss");
-            assertNotNull("validateObj() " + text,  calendar);
-            final Date date = calendar.getTime();
-            assertTrue("isValid() " + text,  validator.isValid(patternValid[i], "HH-mm-ss"));
-            assertEquals("compare " + text, patternExpect[i], date);
-        }
+    @Test
+    public void testCompare() {
+        final int testTime = 154523;
+        final int min = 100;
+        final int hour = 10000;
+
+        final Calendar milliGreater = createTime(GMT, testTime, 500); // > milli sec
+        final Calendar value = createTime(GMT, testTime, 400); // test value
+        final Calendar milliLess = createTime(GMT, testTime, 300); // < milli sec
+
+        final Calendar secGreater = createTime(GMT, testTime + 1, 100); // +1 sec
+        final Calendar secLess = createTime(GMT, testTime - 1, 100); // -1 sec
+
+        final Calendar minGreater = createTime(GMT, testTime + min, 100); // +1 min
+        final Calendar minLess = createTime(GMT, testTime - min, 100); // -1 min
+
+        final Calendar hourGreater = createTime(GMT, testTime + hour, 100); // +1 hour
+        final Calendar hourLess = createTime(GMT, testTime - hour, 100); // -1 hour
+
+        assertEquals(-1, validator.compareTime(value, milliGreater), "mili LT"); // > milli
+        assertEquals(0, validator.compareTime(value, value), "mili EQ"); // same time
+        assertEquals(1, validator.compareTime(value, milliLess), "mili GT"); // < milli
+
+        assertEquals(-1, validator.compareSeconds(value, secGreater), "secs LT"); // +1 sec
+        assertEquals(0, validator.compareSeconds(value, milliGreater), "secs =1"); // > milli
+        assertEquals(0, validator.compareSeconds(value, value), "secs =2"); // same time
+        assertEquals(0, validator.compareSeconds(value, milliLess), "secs =3"); // < milli
+        assertEquals(1, validator.compareSeconds(value, secLess), "secs GT"); // -1 sec
+
+        assertEquals(-1, validator.compareMinutes(value, minGreater), "mins LT"); // +1 min
+        assertEquals(0, validator.compareMinutes(value, secGreater), "mins =1"); // +1 sec
+        assertEquals(0, validator.compareMinutes(value, value), "mins =2"); // same time
+        assertEquals(0, validator.compareMinutes(value, secLess), "mins =3"); // -1 sec
+        assertEquals(1, validator.compareMinutes(value, minLess), "mins GT"); // -1 min
+
+        assertEquals(-1, validator.compareHours(value, hourGreater), "hour LT"); // +1 hour
+        assertEquals(0, validator.compareHours(value, minGreater), "hour =1"); // +1 min
+        assertEquals(0, validator.compareHours(value, value), "hour =2"); // same time
+        assertEquals(0, validator.compareHours(value, minLess), "hour =3"); // -1 min
+        assertEquals(1, validator.compareHours(value, hourLess), "hour GT"); // -1 hour
+
     }
 
     /**
-     * Test Invalid Dates with "pattern" validation
+     * Test Invalid Dates with "locale" validation
      */
-    public void testPatternInvalid() {
-        for (int i = 0; i < patternInvalid.length; i++) {
-            final String text = i + " value=[" +patternInvalid[i]+"] passed ";
-            final Object date = validator.validate(patternInvalid[i], "HH-mm-ss");
-            assertNull("validate() " + text + date,  date);
-            assertFalse("isValid() " + text,  validator.isValid(patternInvalid[i], "HH-mm-ss"));
+    @Test
+    public void testFormat() {
+        // Set the default Locale
+        Locale.setDefault(Locale.UK);
+
+        final Object test = TimeValidator.getInstance().validate("16:49:23", "HH:mm:ss");
+        assertNotNull(test, "Test Date ");
+        assertEquals(validator.format(test, "HH-mm-ss"), "16-49-23", "Format pattern");
+        assertEquals(validator.format(test, Locale.US), "4:49 PM", "Format locale");
+        assertEquals(validator.format(test), "16:49", "Format default");
+
+    }
+
+    /**
+     * Test Invalid Dates with "locale" validation
+     */
+    @Test
+    public void testLocaleInvalid() {
+        for (int i = 0; i < localeInvalid.length; i++) {
+            final String text = i + " value=[" + localeInvalid[i] + "] passed ";
+            final Object date = validator.validate(localeInvalid[i], Locale.US);
+            assertNull(date, () -> "validate() " + text + date);
+            assertFalse(validator.isValid(localeInvalid[i], Locale.UK), () -> "isValid() " + text);
         }
     }
 
     /**
      * Test Valid Dates with "locale" validation
      */
+    @Test
     public void testLocaleValid() {
         for (int i = 0; i < localeValid.length; i++) {
-            final String text = i + " value=[" +localeValid[i]+"] failed ";
+            final String text = i + " value=[" + localeValid[i] + "] failed ";
             final Calendar calendar = validator.validate(localeValid[i], Locale.UK);
-            assertNotNull("validate() " + text,  calendar);
+            assertNotNull(calendar, () -> "validate() " + text);
             final Date date = calendar.getTime();
-            assertTrue("isValid() " + text,  validator.isValid(localeValid[i], Locale.UK));
-            assertEquals("compare " + text, localeExpect[i], date);
+            assertTrue(validator.isValid(localeValid[i], Locale.UK), () -> "isValid() " + text);
+            assertEquals(localeExpect[i], date, () -> "compare " + text);
         }
     }
 
     /**
-     * Test Invalid Dates with "locale" validation
+     * Test Invalid Dates with "pattern" validation
      */
-    public void testLocaleInvalid() {
-        for (int i = 0; i < localeInvalid.length; i++) {
-            final String text = i + " value=[" +localeInvalid[i]+"] passed ";
-            final Object date = validator.validate(localeInvalid[i], Locale.US);
-            assertNull("validate() " + text + date,  date);
-            assertFalse("isValid() " + text,  validator.isValid(localeInvalid[i], Locale.UK));
+    @Test
+    public void testPatternInvalid() {
+        for (int i = 0; i < patternInvalid.length; i++) {
+            final String text = i + " value=[" + patternInvalid[i] + "] passed ";
+            final Object date = validator.validate(patternInvalid[i], "HH-mm-ss");
+            assertNull(date, () -> "validate() " + text + date);
+            assertFalse(validator.isValid(patternInvalid[i], "HH-mm-ss"), () -> "isValid() " + text);
+        }
+    }
+
+    /**
+     * Test Valid Dates with "pattern" validation
+     */
+    @Test
+    public void testPatternValid() {
+        for (int i = 0; i < patternValid.length; i++) {
+            final String text = i + " value=[" + patternValid[i] + "] failed ";
+            final Calendar calendar = validator.validate(patternValid[i], "HH-mm-ss");
+            assertNotNull(calendar, () -> "validateObj() " + text);
+            final Date date = calendar.getTime();
+            assertTrue(validator.isValid(patternValid[i], "HH-mm-ss"), () -> "isValid() " + text);
+            assertEquals(patternExpect[i], date, () -> "compare " + text);
         }
     }
 
     /**
      * Test time zone methods.
      */
+    @Test
     public void testTimeZone() {
         // Set the default Locale & TimeZone
         Locale.setDefault(Locale.UK);
@@ -187,154 +260,57 @@
 
         // Default Locale, Default TimeZone
         result = validator.validate("18:01");
-        assertNotNull("default result", result);
-        assertEquals("default zone",  GMT, result.getTimeZone());
-        assertEquals("default hour",   18, result.get(Calendar.HOUR_OF_DAY));
-        assertEquals("default minute", 01, result.get(Calendar.MINUTE));
+        assertNotNull(result, "default result");
+        assertEquals(GMT, result.getTimeZone(), "default zone");
+        assertEquals(18, result.get(Calendar.HOUR_OF_DAY), "default hour");
+        assertEquals(01, result.get(Calendar.MINUTE), "default minute");
         result = null;
 
         // Default Locale, diff TimeZone
         result = validator.validate("16:49", EST);
-        assertNotNull("zone result", result);
-        assertEquals("zone zone",  EST, result.getTimeZone());
-        assertEquals("zone hour",   16, result.get(Calendar.HOUR_OF_DAY));
-        assertEquals("zone minute", 49, result.get(Calendar.MINUTE));
+        assertNotNull(result, "zone result");
+        assertEquals(EST, result.getTimeZone(), "zone zone");
+        assertEquals(16, result.get(Calendar.HOUR_OF_DAY), "zone hour");
+        assertEquals(49, result.get(Calendar.MINUTE), "zone minute");
         result = null;
 
         // Pattern, diff TimeZone
         result = validator.validate("14-34", "HH-mm", EST);
-        assertNotNull("pattern result", result);
-        assertEquals("pattern zone",  EST, result.getTimeZone());
-        assertEquals("pattern hour",   14, result.get(Calendar.HOUR_OF_DAY));
-        assertEquals("pattern minute", 34, result.get(Calendar.MINUTE));
+        assertNotNull(result, "pattern result");
+        assertEquals(EST, result.getTimeZone(), "pattern zone");
+        assertEquals(14, result.get(Calendar.HOUR_OF_DAY), "pattern hour");
+        assertEquals(34, result.get(Calendar.MINUTE), "pattern minute");
         result = null;
 
         // Locale, diff TimeZone
         result = validator.validate("7:18 PM", Locale.US, EST);
-        assertNotNull("locale result", result);
-        assertEquals("locale zone",  EST, result.getTimeZone());
-        assertEquals("locale hour",   19, result.get(Calendar.HOUR_OF_DAY));
-        assertEquals("locale minute", 18, result.get(Calendar.MINUTE));
+        assertNotNull(result, "locale result");
+        assertEquals(EST, result.getTimeZone(), "locale zone");
+        assertEquals(19, result.get(Calendar.HOUR_OF_DAY), "locale hour");
+        assertEquals(18, result.get(Calendar.MINUTE), "locale minute");
         result = null;
 
         // Locale & Pattern, diff TimeZone
         result = validator.validate("31/Dez/05 21-05", "dd/MMM/yy HH-mm", Locale.GERMAN, EST);
-        assertNotNull("pattern result", result);
-        assertEquals("pattern zone",  EST, result.getTimeZone());
-        assertEquals("pattern day",  2005, result.get(Calendar.YEAR));
-        assertEquals("pattern day",    11, result.get(Calendar.MONTH)); // months are 0-11
-        assertEquals("pattern day",    31, result.get(Calendar.DATE));
-        assertEquals("pattern hour",   21, result.get(Calendar.HOUR_OF_DAY));
-        assertEquals("pattern minute", 05, result.get(Calendar.MINUTE));
+        assertNotNull(result, "pattern result");
+        assertEquals(EST, result.getTimeZone(), "pattern zone");
+        assertEquals(2005, result.get(Calendar.YEAR), "pattern day");
+        assertEquals(11, result.get(Calendar.MONTH), "pattern day"); // months are 0-11
+        assertEquals(31, result.get(Calendar.DATE), "pattern day");
+        assertEquals(21, result.get(Calendar.HOUR_OF_DAY), "pattern hour");
+        assertEquals(05, result.get(Calendar.MINUTE), "pattern minute");
         result = null;
 
         // Locale & Pattern, default TimeZone
         result = validator.validate("31/Dez/05 21-05", "dd/MMM/yy HH-mm", Locale.GERMAN);
-        assertNotNull("pattern result", result);
-        assertEquals("pattern zone",  GMT, result.getTimeZone());
-        assertEquals("pattern day",  2005, result.get(Calendar.YEAR));
-        assertEquals("pattern day",    11, result.get(Calendar.MONTH)); // months are 0-11
-        assertEquals("pattern day",    31, result.get(Calendar.DATE));
-        assertEquals("pattern hour",   21, result.get(Calendar.HOUR_OF_DAY));
-        assertEquals("pattern minute", 05, result.get(Calendar.MINUTE));
+        assertNotNull(result, "pattern result");
+        assertEquals(GMT, result.getTimeZone(), "pattern zone");
+        assertEquals(2005, result.get(Calendar.YEAR), "pattern day");
+        assertEquals(11, result.get(Calendar.MONTH), "pattern day"); // months are 0-11
+        assertEquals(31, result.get(Calendar.DATE), "pattern day");
+        assertEquals(21, result.get(Calendar.HOUR_OF_DAY), "pattern hour");
+        assertEquals(05, result.get(Calendar.MINUTE), "pattern minute");
         result = null;
 
     }
-
-    /**
-     * Test Invalid Dates with "locale" validation
-     */
-    public void testFormat() {
-        // Set the default Locale
-        Locale.setDefault(Locale.UK);
-
-        final Object test = TimeValidator.getInstance().validate("16:49:23", "HH:mm:ss");
-        assertNotNull("Test Date ", test);
-        assertEquals("Format pattern", "16-49-23", validator.format(test, "HH-mm-ss"));
-        assertEquals("Format locale",  "4:49 PM",  validator.format(test, Locale.US));
-        assertEquals("Format default", "16:49",  validator.format(test));
-
-    }
-
-    /**
-     * Test compare date methods
-     */
-    public void testCompare() {
-        final int testTime = 154523;
-        final int min = 100;
-        final int hour = 10000;
-
-        final Calendar milliGreater = createTime(GMT, testTime, 500); // > milli sec
-        final Calendar value        = createTime(GMT, testTime, 400); // test value
-        final Calendar milliLess    = createTime(GMT, testTime, 300); // < milli sec
-
-        final Calendar secGreater   = createTime(GMT, testTime + 1, 100);   // +1 sec
-        final Calendar secLess      = createTime(GMT, testTime - 1, 100);   // -1 sec
-
-        final Calendar minGreater   = createTime(GMT, testTime + min, 100);   // +1 min
-        final Calendar minLess      = createTime(GMT, testTime - min, 100);   // -1 min
-
-        final Calendar hourGreater  = createTime(GMT, testTime + hour, 100);   // +1 hour
-        final Calendar hourLess     = createTime(GMT, testTime - hour, 100);   // -1 hour
-
-        assertEquals("mili LT", -1, validator.compareTime(value, milliGreater)); // > milli
-        assertEquals("mili EQ", 0,  validator.compareTime(value, value));        // same time
-        assertEquals("mili GT", 1,  validator.compareTime(value, milliLess));    // < milli
-
-        assertEquals("secs LT", -1, validator.compareSeconds(value, secGreater));   // +1 sec
-        assertEquals("secs =1", 0,  validator.compareSeconds(value, milliGreater)); // > milli
-        assertEquals("secs =2", 0,  validator.compareSeconds(value, value));        // same time
-        assertEquals("secs =3", 0,  validator.compareSeconds(value, milliLess));    // < milli
-        assertEquals("secs GT", 1,  validator.compareSeconds(value, secLess));      // -1 sec
-
-        assertEquals("mins LT", -1, validator.compareMinutes(value, minGreater));   // +1 min
-        assertEquals("mins =1", 0,  validator.compareMinutes(value, secGreater));   // +1 sec
-        assertEquals("mins =2", 0,  validator.compareMinutes(value, value));        // same time
-        assertEquals("mins =3", 0,  validator.compareMinutes(value, secLess));      // -1 sec
-        assertEquals("mins GT", 1,  validator.compareMinutes(value, minLess));      // -1 min
-
-        assertEquals("hour LT", -1, validator.compareHours(value, hourGreater));   // +1 hour
-        assertEquals("hour =1", 0,  validator.compareHours(value, minGreater));   // +1 min
-        assertEquals("hour =2", 0,  validator.compareHours(value, value));        // same time
-        assertEquals("hour =3", 0,  validator.compareHours(value, minLess));      // -1 min
-        assertEquals("hour GT", 1,  validator.compareHours(value, hourLess));      // -1 hour
-
-    }
-
-    /**
-     * Create a calendar instance for a specified time zone, date and time.
-     *
-     * @param zone The time zone
-     * @param time the time in HH:mm:ss format
-     * @param millisecond the milliseconds
-     * @return the new Calendar instance.
-     */
-    protected static Calendar createTime(final TimeZone zone, final int time, final int millisecond) {
-        final Calendar calendar = zone == null ? Calendar.getInstance()
-                                         : Calendar.getInstance(zone);
-        final int hour = ((time / 10000) * 10000);
-        final int min  = ((time / 100) * 100) - hour;
-        final int sec  = time - (hour + min);
-        calendar.set(Calendar.YEAR,  1970);
-        calendar.set(Calendar.MONTH, 0);
-        calendar.set(Calendar.DATE,  1);
-        calendar.set(Calendar.HOUR_OF_DAY,  (hour / 10000));
-        calendar.set(Calendar.MINUTE, (min / 100));
-        calendar.set(Calendar.SECOND,  sec);
-        calendar.set(Calendar.MILLISECOND,  millisecond);
-        return calendar;
-    }
-
-    /**
-     * Create a date instance for a specified time zone, date and time.
-     *
-     * @param zone The time zone
-     * @param time the time in HH:mm:ss format
-     * @param millisecond the milliseconds
-     * @return the new Date instance.
-     */
-    protected static Date createDate(final TimeZone zone, final int time, final int millisecond) {
-        final Calendar calendar = createTime(zone, time, millisecond);
-        return calendar.getTime();
-    }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/UrlValidatorTest.java b/src/test/java/org/apache/commons/validator/routines/UrlValidatorTest.java
index 1e4f306..af4a76a 100644
--- a/src/test/java/org/apache/commons/validator/routines/UrlValidatorTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/UrlValidatorTest.java
@@ -19,10 +19,10 @@
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.core.Is.is;
 import static org.hamcrest.core.IsEqual.equalTo;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertThrows;
-import static org.junit.Assert.assertTrue;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.junit.jupiter.api.Assertions.assertTrue;
 
 import java.net.URI;
 import java.net.URISyntaxException;
@@ -31,207 +31,292 @@
 
 import org.apache.commons.validator.ResultPair;
 import org.junit.Before;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 /**
  * Performs Validation Test for url validations.
  */
 public class UrlValidatorTest {
 
-   private final boolean printStatus = false;
-   private final boolean printIndex = false;//print index that indicates current scheme,host,port,path, query test were using.
+    static boolean incrementTestPartsIndex(final int[] testPartsIndex, final Object[] testParts) {
+        boolean carry = true; // add 1 to lowest order part.
+        boolean maxIndex = true;
+        for (int testPartsIndexIndex = testPartsIndex.length - 1; testPartsIndexIndex >= 0; --testPartsIndexIndex) {
+            int index = testPartsIndex[testPartsIndexIndex];
+            final ResultPair[] part = (ResultPair[]) testParts[testPartsIndexIndex];
+            maxIndex &= index == part.length - 1;
+            if (carry) {
+                if (index < part.length - 1) {
+                    index++;
+                    testPartsIndex[testPartsIndexIndex] = index;
+                    carry = false;
+                } else {
+                    testPartsIndex[testPartsIndexIndex] = 0;
+                    carry = true;
+                }
+            }
+        }
 
-   @Before
-   public void setUp() {
-      for (int index = 0; index < testPartsIndex.length - 1; index++) {
-         testPartsIndex[index] = 0;
-      }
-   }
+        return !maxIndex;
+    }
 
-   @Test
-   public void testIsValid() {
+    /**
+     * Validator for checking URL parsing
+     *
+     * @param args - URLs to validate
+     */
+    public static void main(final String[] args) {
+        final UrlValidator uv = new UrlValidator();
+        for (final String arg : args) {
+            try {
+                URI uri = new URI(arg);
+                uri = uri.normalize();
+                System.out.println(uri.toString());
+                System.out.printf("URI scheme: %s%n", uri.getScheme());
+                System.out.printf("URI scheme specific part: %s%n", uri.getSchemeSpecificPart());
+                System.out.printf("URI raw scheme specific part: %s%n", uri.getRawSchemeSpecificPart());
+                System.out.printf("URI auth: %s%n", uri.getAuthority());
+                System.out.printf("URI raw auth: %s%n", uri.getRawAuthority());
+                System.out.printf("URI userInfo: %s%n", uri.getUserInfo());
+                System.out.printf("URI raw userInfo: %s%n", uri.getRawUserInfo());
+                System.out.printf("URI host: %s%n", uri.getHost());
+                System.out.printf("URI port: %s%n", uri.getPort());
+                System.out.printf("URI path: %s%n", uri.getPath());
+                System.out.printf("URI raw path: %s%n", uri.getRawPath());
+                System.out.printf("URI query: %s%n", uri.getQuery());
+                System.out.printf("URI raw query: %s%n", uri.getRawQuery());
+                System.out.printf("URI fragment: %s%n", uri.getFragment());
+                System.out.printf("URI raw fragment: %s%n", uri.getRawFragment());
+            } catch (final URISyntaxException e) {
+                System.out.println(e.getMessage());
+            }
+            System.out.printf("isValid: %s%n", uv.isValid(arg));
+        }
+    }
+
+    private final boolean printStatus = false;
+
+    private final boolean printIndex = false;// print index that indicates current scheme,host,port,path, query test were using.
+
+    /**
+     * The data given below approximates the 4 parts of a URL <scheme>://<authority><path>?<query> except that the port number is broken out of authority to
+     * increase the number of permutations. A complete URL is composed of a scheme+authority+port+path+query, all of which must be individually valid for the
+     * entire URL to be considered valid.
+     */
+    ResultPair[] testUrlScheme = { new ResultPair("http://", true), new ResultPair("ftp://", true), new ResultPair("h3t://", true),
+            new ResultPair("3ht://", false), new ResultPair("http:/", false), new ResultPair("http:", false), new ResultPair("http/", false),
+            new ResultPair("://", false) };
+
+    ResultPair[] testUrlAuthority = { new ResultPair("www.google.com", true), new ResultPair("www.google.com.", true), new ResultPair("go.com", true),
+            new ResultPair("go.au", true), new ResultPair("0.0.0.0", true), new ResultPair("255.255.255.255", true), new ResultPair("256.256.256.256", false),
+            new ResultPair("255.com", true), new ResultPair("1.2.3.4.5", false), new ResultPair("1.2.3.4.", false), new ResultPair("1.2.3", false),
+            new ResultPair(".1.2.3.4", false), new ResultPair("go.a", false), new ResultPair("go.a1a", false), new ResultPair("go.cc", true),
+            new ResultPair("go.1aa", false), new ResultPair("aaa.", false), new ResultPair(".aaa", false), new ResultPair("aaa", false),
+            new ResultPair("", false) };
+
+    ResultPair[] testUrlPort = { new ResultPair(":80", true), new ResultPair(":65535", true), // max possible
+            new ResultPair(":65536", false), // max possible +1
+            new ResultPair(":0", true), new ResultPair("", true), new ResultPair(":-1", false), new ResultPair(":65636", false),
+            new ResultPair(":999999999999999999", false), new ResultPair(":65a", false) };
+
+    ResultPair[] testPath = { new ResultPair("/test1", true), new ResultPair("/t123", true), new ResultPair("/$23", true), new ResultPair("/..", false),
+            new ResultPair("/../", false), new ResultPair("/test1/", true), new ResultPair("", true), new ResultPair("/test1/file", true),
+            new ResultPair("/..//file", false), new ResultPair("/test1//file", false) };
+
+    // Test allow2slash, noFragment
+    ResultPair[] testUrlPathOptions = { new ResultPair("/test1", true), new ResultPair("/t123", true), new ResultPair("/$23", true),
+            new ResultPair("/..", false), new ResultPair("/../", false), new ResultPair("/test1/", true), new ResultPair("/#", false), new ResultPair("", true),
+            new ResultPair("/test1/file", true), new ResultPair("/t123/file", true), new ResultPair("/$23/file", true), new ResultPair("/../file", false),
+            new ResultPair("/..//file", false), new ResultPair("/test1//file", true), new ResultPair("/#/file", false) };
+
+    ResultPair[] testUrlQuery = { new ResultPair("?action=view", true), new ResultPair("?action=edit&mode=up", true), new ResultPair("", true) };
+
+    Object[] testUrlParts = { testUrlScheme, testUrlAuthority, testUrlPort, testPath, testUrlQuery };
+
+    Object[] testUrlPartsOptions = { testUrlScheme, testUrlAuthority, testUrlPort, testUrlPathOptions, testUrlQuery };
+
+    int[] testPartsIndex = { 0, 0, 0, 0, 0 };
+
+    // ---------------- Test data for individual url parts ----------------
+    private final String[] schemes = { "http", "gopher", "g0-To+.", "not_valid" // TODO this will need to be dropped if the ctor validates schemes
+    };
+
+    ResultPair[] testScheme = { new ResultPair("http", true), new ResultPair("ftp", false), new ResultPair("httpd", false), new ResultPair("gopher", true),
+            new ResultPair("g0-to+.", true), new ResultPair("not_valid", false), // underscore not allowed
+            new ResultPair("HtTp", true), new ResultPair("telnet", false) };
+
+    @Before
+    public void setUp() {
+        for (int index = 0; index < testPartsIndex.length - 1; index++) {
+            testPartsIndex[index] = 0;
+        }
+    }
+
+    @Test
+    public void testFragments() {
+        final String[] schemes = { "http", "https" };
+        UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.NO_FRAGMENTS);
+        assertFalse(urlValidator.isValid("http://apache.org/a/b/c#frag"));
+        urlValidator = new UrlValidator(schemes);
+        assertTrue(urlValidator.isValid("http://apache.org/a/b/c#frag"));
+    }
+
+    @Test
+    public void testIsValid() {
         testIsValid(testUrlParts, UrlValidator.ALLOW_ALL_SCHEMES);
         setUp();
-        final long options =
-            UrlValidator.ALLOW_2_SLASHES
-                + UrlValidator.ALLOW_ALL_SCHEMES
-                + UrlValidator.NO_FRAGMENTS;
+        final long options = UrlValidator.ALLOW_2_SLASHES + UrlValidator.ALLOW_ALL_SCHEMES + UrlValidator.NO_FRAGMENTS;
 
         testIsValid(testUrlPartsOptions, options);
-   }
+    }
 
-   @Test
-   public void testIsValidScheme() {
-      if (printStatus) {
-         System.out.print("\n testIsValidScheme() ");
-      }
-      //UrlValidator urlVal = new UrlValidator(schemes,false,false,false);
-      final UrlValidator urlVal = new UrlValidator(schemes, 0);
-      for (final ResultPair testPair : testScheme) {
-         final boolean result = urlVal.isValidScheme(testPair.item);
-         assertEquals(testPair.item, testPair.valid, result);
-         if (printStatus) {
-            if (result == testPair.valid) {
-               System.out.print('.');
+    /**
+     * Create set of tests by taking the testUrlXXX arrays and running through all possible permutations of their combinations.
+     *
+     * @param testObjects Used to create a url.
+     */
+    public void testIsValid(final Object[] testObjects, final long options) {
+        final UrlValidator urlVal = new UrlValidator(null, null, options);
+        assertTrue(urlVal.isValid("http://www.google.com"));
+        assertTrue(urlVal.isValid("http://www.google.com/"));
+        int statusPerLine = 60;
+        int printed = 0;
+        if (printIndex) {
+            statusPerLine = 6;
+        }
+        do {
+            final StringBuilder testBuffer = new StringBuilder();
+            boolean expected = true;
+            for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) {
+                final int index = testPartsIndex[testPartsIndexIndex];
+                final ResultPair[] part = (ResultPair[]) testObjects[testPartsIndexIndex];
+                testBuffer.append(part[index].item);
+                expected &= part[index].valid;
+            }
+            final String url = testBuffer.toString();
+            final boolean result = urlVal.isValid(url);
+            assertEquals(expected, result, url);
+            if (printStatus) {
+                if (printIndex) {
+                    System.out.print(testPartsIndextoString());
+                } else if (result == expected) {
+                    System.out.print('.');
+                } else {
+                    System.out.print('X');
+                }
+                printed++;
+                if (printed == statusPerLine) {
+                    System.out.println();
+                    printed = 0;
+                }
+            }
+        } while (incrementTestPartsIndex(testPartsIndex, testObjects));
+        if (printStatus) {
+            System.out.println();
+        }
+    }
+
+    @Test
+    public void testIsValidScheme() {
+        if (printStatus) {
+            System.out.print("\n testIsValidScheme() ");
+        }
+        // UrlValidator urlVal = new UrlValidator(schemes,false,false,false);
+        final UrlValidator urlVal = new UrlValidator(schemes, 0);
+        for (final ResultPair testPair : testScheme) {
+            final boolean result = urlVal.isValidScheme(testPair.item);
+            assertEquals(testPair.valid, result, testPair.item);
+            if (printStatus) {
+                if (result == testPair.valid) {
+                    System.out.print('.');
+                } else {
+                    System.out.print('X');
+                }
+            }
+        }
+        if (printStatus) {
+            System.out.println();
+        }
+
+    }
+
+    private String testPartsIndextoString() {
+        final StringBuilder carryMsg = new StringBuilder("{");
+        for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) {
+            carryMsg.append(testPartsIndex[testPartsIndexIndex]);
+            if (testPartsIndexIndex < testPartsIndex.length - 1) {
+                carryMsg.append(',');
             } else {
-               System.out.print('X');
+                carryMsg.append('}');
             }
-         }
-      }
-      if (printStatus) {
-         System.out.println();
-      }
+        }
+        return carryMsg.toString();
 
-   }
+    }
 
-   /**
-    * Create set of tests by taking the testUrlXXX arrays and
-    * running through all possible permutations of their combinations.
-    *
-    * @param testObjects Used to create a url.
-    */
-   public void testIsValid(final Object[] testObjects, final long options) {
-      final UrlValidator urlVal = new UrlValidator(null, null, options);
-      assertTrue(urlVal.isValid("http://www.google.com"));
-      assertTrue(urlVal.isValid("http://www.google.com/"));
-      int statusPerLine = 60;
-      int printed = 0;
-      if (printIndex)  {
-         statusPerLine = 6;
-      }
-      do {
-          final StringBuilder testBuffer = new StringBuilder();
-         boolean expected = true;
-         for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) {
-            final int index = testPartsIndex[testPartsIndexIndex];
-            final ResultPair[] part = (ResultPair[]) testObjects[testPartsIndexIndex];
-            testBuffer.append(part[index].item);
-            expected &= part[index].valid;
-         }
-         final String url = testBuffer.toString();
-         final boolean result = urlVal.isValid(url);
-         assertEquals(url, expected, result);
-         if (printStatus) {
-            if (printIndex) {
-               System.out.print(testPartsIndextoString());
-            } else if (result == expected) {
-                  System.out.print('.');
-               } else {
-                  System.out.print('X');
-               }
-            printed++;
-            if (printed == statusPerLine) {
-               System.out.println();
-               printed = 0;
-            }
-         }
-      } while (incrementTestPartsIndex(testPartsIndex, testObjects));
-      if (printStatus) {
-         System.out.println();
-      }
-   }
+    @Test
+    public void testValidateUrl() {
+        assertTrue(true);
+    }
 
-   @Test
-   public void testValidator202() {
-       final String[] schemes = {"http","https"};
-       final UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.NO_FRAGMENTS);
-       assertTrue(urlValidator.isValid("http://l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.org"));
-   }
+    @Test
+    public void testValidator202() {
+        final String[] schemes = { "http", "https" };
+        final UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.NO_FRAGMENTS);
+        assertTrue(urlValidator
+                .isValid("http://l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.l.org"));
+    }
 
-   @Test
-   public void testValidator204() {
-       final String[] schemes = {"http","https"};
-       final UrlValidator urlValidator = new UrlValidator(schemes);
-       assertTrue(urlValidator.isValid("http://tech.yahoo.com/rc/desktops/102;_ylt=Ao8yevQHlZ4On0O3ZJGXLEQFLZA5"));
-   }
+    @Test
+    public void testValidator204() {
+        final String[] schemes = { "http", "https" };
+        final UrlValidator urlValidator = new UrlValidator(schemes);
+        assertTrue(urlValidator.isValid("http://tech.yahoo.com/rc/desktops/102;_ylt=Ao8yevQHlZ4On0O3ZJGXLEQFLZA5"));
+    }
 
-   @Test
-   public void testValidator218() {
-       final UrlValidator validator = new UrlValidator(UrlValidator.ALLOW_2_SLASHES);
-       assertTrue("parentheses should be valid in URLs",
-               validator.isValid("http://somewhere.com/pathxyz/file(1).html"));
-   }
+    @Test
+    public void testValidator218() {
+        final UrlValidator validator = new UrlValidator(UrlValidator.ALLOW_2_SLASHES);
+        assertTrue(validator.isValid("http://somewhere.com/pathxyz/file(1).html"), "parentheses should be valid in URLs");
+    }
 
-   @Test
-   public void testValidator235() {
-       final String version = System.getProperty("java.version");
-       if (version.compareTo("1.6") < 0) {
-           System.out.println("Cannot run Unicode IDN tests");
-           return; // Cannot run the test
-       }
-       final UrlValidator validator = new UrlValidator();
-       assertTrue("xn--d1abbgf6aiiy.xn--p1ai should validate", validator.isValid("http://xn--d1abbgf6aiiy.xn--p1ai"));
-       assertTrue("ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„ should validate", validator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„"));
-       assertTrue("www.b\u00fccher.ch should validate", validator.isValid("http://www.b\u00fccher.ch"));
-       assertFalse("www.\uFFFD.ch FFFD should fail", validator.isValid("http://www.\uFFFD.ch"));
-       assertTrue("www.b\u00fccher.ch should validate", validator.isValid("ftp://www.b\u00fccher.ch"));
-       assertFalse("www.\uFFFD.ch FFFD should fail", validator.isValid("ftp://www.\uFFFD.ch"));
-   }
+    @Test
+    public void testValidator235() {
+        final String version = System.getProperty("java.version");
+        if (version.compareTo("1.6") < 0) {
+            System.out.println("Cannot run Unicode IDN tests");
+            return; // Cannot run the test
+        }
+        final UrlValidator validator = new UrlValidator();
+        assertTrue(validator.isValid("http://xn--d1abbgf6aiiy.xn--p1ai"), "xn--d1abbgf6aiiy.xn--p1ai should validate");
+        assertTrue(validator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„"), "ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„ should validate");
+        assertTrue(validator.isValid("http://www.b\u00fccher.ch"), "www.b\u00fccher.ch should validate");
+        assertFalse(validator.isValid("http://www.\uFFFD.ch"), "www.\uFFFD.ch FFFD should fail");
+        assertTrue(validator.isValid("ftp://www.b\u00fccher.ch"), "www.b\u00fccher.ch should validate");
+        assertFalse(validator.isValid("ftp://www.\uFFFD.ch"), "www.\uFFFD.ch FFFD should fail");
+    }
 
     @Test
     public void testValidator248() {
-        final RegexValidator regex = new RegexValidator(new String[] {"localhost", ".*\\.my-testing"});
+        final RegexValidator regex = new RegexValidator("localhost", ".*\\.my-testing");
         UrlValidator validator = new UrlValidator(regex, 0);
 
-        assertTrue("localhost URL should validate",
-                validator.isValid("http://localhost/test/index.html"));
-        assertTrue("first.my-testing should validate",
-                validator.isValid("http://first.my-testing/test/index.html"));
-        assertTrue("sup3r.my-testing should validate",
-                validator.isValid("http://sup3r.my-testing/test/index.html"));
+        assertTrue(validator.isValid("http://localhost/test/index.html"), "localhost URL should validate");
+        assertTrue(validator.isValid("http://first.my-testing/test/index.html"), "first.my-testing should validate");
+        assertTrue(validator.isValid("http://sup3r.my-testing/test/index.html"), "sup3r.my-testing should validate");
 
-        assertFalse("broke.my-test should not validate",
-                validator.isValid("http://broke.my-test/test/index.html"));
+        assertFalse(validator.isValid("http://broke.my-test/test/index.html"), "broke.my-test should not validate");
 
-        assertTrue("www.apache.org should still validate",
-                validator.isValid("http://www.apache.org/test/index.html"));
+        assertTrue(validator.isValid("http://www.apache.org/test/index.html"), "www.apache.org should still validate");
 
         // Now check using options
         validator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS);
 
-        assertTrue("localhost URL should validate",
-              validator.isValid("http://localhost/test/index.html"));
+        assertTrue(validator.isValid("http://localhost/test/index.html"), "localhost URL should validate");
 
-        assertTrue("machinename URL should validate",
-              validator.isValid("http://machinename/test/index.html"));
+        assertTrue(validator.isValid("http://machinename/test/index.html"), "machinename URL should validate");
 
-        assertTrue("www.apache.org should still validate",
-              validator.isValid("http://www.apache.org/test/index.html"));
-    }
-
-    @Test
-    public void testValidator288() {
-        UrlValidator validator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS);
-
-        assertTrue("hostname should validate",
-                validator.isValid("http://hostname"));
-
-        assertTrue("hostname with path should validate",
-                validator.isValid("http://hostname/test/index.html"));
-
-        assertTrue("localhost URL should validate",
-                validator.isValid("http://localhost/test/index.html"));
-
-        assertFalse("first.my-testing should not validate",
-                validator.isValid("http://first.my-testing/test/index.html"));
-
-        assertFalse("broke.hostname should not validate",
-                validator.isValid("http://broke.hostname/test/index.html"));
-
-        assertTrue("www.apache.org should still validate",
-                validator.isValid("http://www.apache.org/test/index.html"));
-
-        // Turn it off, and check
-        validator = new UrlValidator(0);
-
-        assertFalse("hostname should no longer validate",
-                validator.isValid("http://hostname"));
-
-        assertFalse("localhost URL should no longer validate",
-                validator.isValid("http://localhost/test/index.html"));
-
-        assertTrue("www.apache.org should still validate",
-                validator.isValid("http://www.apache.org/test/index.html"));
+        assertTrue(validator.isValid("http://www.apache.org/test/index.html"), "www.apache.org should still validate");
     }
 
     @Test
@@ -239,203 +324,81 @@
         // file:// isn't allowed by default
         UrlValidator validator = new UrlValidator();
 
-        assertTrue("http://apache.org/ should be allowed by default",
-                 validator.isValid("http://www.apache.org/test/index.html"));
+        assertTrue(validator.isValid("http://www.apache.org/test/index.html"), "http://apache.org/ should be allowed by default");
 
-        assertFalse("file:///c:/ shouldn't be allowed by default",
-                 validator.isValid("file:///C:/some.file"));
+        assertFalse(validator.isValid("file:///C:/some.file"), "file:///c:/ shouldn't be allowed by default");
 
-        assertFalse("file:///c:\\ shouldn't be allowed by default",
-              validator.isValid("file:///C:\\some.file"));
+        assertFalse(validator.isValid("file:///C:\\some.file"), "file:///c:\\ shouldn't be allowed by default");
 
-        assertFalse("file:///etc/ shouldn't be allowed by default",
-              validator.isValid("file:///etc/hosts"));
+        assertFalse(validator.isValid("file:///etc/hosts"), "file:///etc/ shouldn't be allowed by default");
 
-        assertFalse("file://localhost/etc/ shouldn't be allowed by default",
-              validator.isValid("file://localhost/etc/hosts"));
+        assertFalse(validator.isValid("file://localhost/etc/hosts"), "file://localhost/etc/ shouldn't be allowed by default");
 
-        assertFalse("file://localhost/c:/ shouldn't be allowed by default",
-              validator.isValid("file://localhost/c:/some.file"));
+        assertFalse(validator.isValid("file://localhost/c:/some.file"), "file://localhost/c:/ shouldn't be allowed by default");
 
         // Turn it on, and check
         // Note - we need to enable local urls when working with file:
-        validator = new UrlValidator(new String[] {"http","file"}, UrlValidator.ALLOW_LOCAL_URLS);
+        validator = new UrlValidator(new String[] { "http", "file" }, UrlValidator.ALLOW_LOCAL_URLS);
 
-        assertTrue("http://apache.org/ should be allowed by default",
-                 validator.isValid("http://www.apache.org/test/index.html"));
+        assertTrue(validator.isValid("http://www.apache.org/test/index.html"), "http://apache.org/ should be allowed by default");
 
-        assertTrue("file:///c:/ should now be allowed",
-                 validator.isValid("file:///C:/some.file"));
+        assertTrue(validator.isValid("file:///C:/some.file"), "file:///c:/ should now be allowed");
 
-        assertFalse("file:///c:\\ should not be allowed", // Only allow forward slashes
-              validator.isValid("file:///C:\\some.file"));
+        // Only allow forward slashes
+        assertFalse(validator.isValid("file:///C:\\some.file"), "file:///c:\\ should not be allowed");
 
-        assertTrue("file:///etc/ should now be allowed",
-              validator.isValid("file:///etc/hosts"));
+        assertTrue(validator.isValid("file:///etc/hosts"), "file:///etc/ should now be allowed");
 
-        assertTrue("file://localhost/etc/ should now be allowed",
-              validator.isValid("file://localhost/etc/hosts"));
+        assertTrue(validator.isValid("file://localhost/etc/hosts"), "file://localhost/etc/ should now be allowed");
 
-        assertTrue("file://localhost/c:/ should now be allowed",
-              validator.isValid("file://localhost/c:/some.file"));
+        assertTrue(validator.isValid("file://localhost/c:/some.file"), "file://localhost/c:/ should now be allowed");
 
         // These are never valid
-        assertFalse("file://c:/ shouldn't ever be allowed, needs file:///c:/",
-              validator.isValid("file://C:/some.file"));
+        assertFalse(validator.isValid("file://C:/some.file"), "file://c:/ shouldn't ever be allowed, needs file:///c:/");
 
-        assertFalse("file://c:\\ shouldn't ever be allowed, needs file:///c:/",
-              validator.isValid("file://C:\\some.file"));
+        assertFalse(validator.isValid("file://C:\\some.file"), "file://c:\\ shouldn't ever be allowed, needs file:///c:/");
     }
 
     @Test
-    public void testValidator391OK() {
-        final String[] schemes = {"file"};
-        final UrlValidator urlValidator = new UrlValidator(schemes);
-        assertTrue(urlValidator.isValid("file:///C:/path/to/dir/"));
+    public void testValidator283() {
+        final UrlValidator validator = new UrlValidator();
+        assertFalse(validator.isValid("http://finance.yahoo.com/news/Owners-54B-NY-housing-apf-2493139299.html?x=0&ap=%fr"));
+        assertTrue(validator.isValid("http://finance.yahoo.com/news/Owners-54B-NY-housing-apf-2493139299.html?x=0&ap=%22"));
     }
 
     @Test
-    public void testValidator391FAILS() {
-        final String[] schemes = {"file"};
-        final UrlValidator urlValidator = new UrlValidator(schemes);
-        assertTrue(urlValidator.isValid("file:/C:/path/to/dir/"));
+    public void testValidator288() {
+        UrlValidator validator = new UrlValidator(UrlValidator.ALLOW_LOCAL_URLS);
+
+        assertTrue(validator.isValid("http://hostname"), "hostname should validate");
+
+        assertTrue(validator.isValid("http://hostname/test/index.html"), "hostname with path should validate");
+
+        assertTrue(validator.isValid("http://localhost/test/index.html"), "localhost URL should validate");
+
+        assertFalse(validator.isValid("http://first.my-testing/test/index.html"), "first.my-testing should not validate");
+
+        assertFalse(validator.isValid("http://broke.hostname/test/index.html"), "broke.hostname should not validate");
+
+        assertTrue(validator.isValid("http://www.apache.org/test/index.html"), "www.apache.org should still validate");
+
+        // Turn it off, and check
+        validator = new UrlValidator(0);
+
+        assertFalse(validator.isValid("http://hostname"), "hostname should no longer validate");
+
+        assertFalse(validator.isValid("http://localhost/test/index.html"), "localhost URL should no longer validate");
+
+        assertTrue(validator.isValid("http://www.apache.org/test/index.html"), "www.apache.org should still validate");
     }
 
     @Test
-    public void testValidator309() {
-        UrlValidator urlValidator = new UrlValidator();
-        assertTrue(urlValidator.isValid("http://sample.ondemand.com/"));
-        assertTrue(urlValidator.isValid("hTtP://sample.ondemand.CoM/"));
-        assertTrue(urlValidator.isValid("httpS://SAMPLE.ONEMAND.COM/"));
-        urlValidator = new UrlValidator(new String[] {"HTTP","HTTPS"});
-        assertTrue(urlValidator.isValid("http://sample.ondemand.com/"));
-        assertTrue(urlValidator.isValid("hTtP://sample.ondemand.CoM/"));
-        assertTrue(urlValidator.isValid("httpS://SAMPLE.ONEMAND.COM/"));
-    }
-
-    @Test
-    public void testValidator339(){
-        final UrlValidator urlValidator = new UrlValidator();
-        assertTrue(urlValidator.isValid("http://www.cnn.com/WORLD/?hpt=sitenav")); // without
-        assertTrue(urlValidator.isValid("http://www.cnn.com./WORLD/?hpt=sitenav")); // with
-        assertFalse(urlValidator.isValid("http://www.cnn.com../")); // doubly dotty
-        assertFalse(urlValidator.isValid("http://www.cnn.invalid/"));
-        assertFalse(urlValidator.isValid("http://www.cnn.invalid./")); // check . does not affect invalid domains
-    }
-
-    @Test
-    public void testValidator339IDN(){
-        final UrlValidator urlValidator = new UrlValidator();
-        assertTrue(urlValidator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„/WORLD/?hpt=sitenav")); // without
-        assertTrue(urlValidator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„./WORLD/?hpt=sitenav")); // with
-        assertFalse(urlValidator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„..../")); // very dotty
-        assertFalse(urlValidator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„.../")); // triply dotty
-        assertFalse(urlValidator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„../")); // doubly dotty
-    }
-
-    @Test
-    public void testValidator342(){
-        final UrlValidator urlValidator = new UrlValidator();
-        assertTrue(urlValidator.isValid("http://example.rocks/"));
-        assertTrue(urlValidator.isValid("http://example.rocks"));
-    }
-
-    @Test
-    public void testValidator411(){
-        final UrlValidator urlValidator = new UrlValidator();
-        assertTrue(urlValidator.isValid("http://example.rocks:/"));
-        assertTrue(urlValidator.isValid("http://example.rocks:0/"));
-        assertTrue(urlValidator.isValid("http://example.rocks:65535/"));
-        assertFalse(urlValidator.isValid("http://example.rocks:65536/"));
-        assertFalse(urlValidator.isValid("http://example.rocks:100000/"));
-    }
-
-    @Test
-    public void testValidator464() {
-        final String[] schemes = {"file"};
-        final UrlValidator urlValidator = new UrlValidator(schemes);
-        final String fileNAK = "file://bad ^ domain.com/label/test";
-        assertFalse(fileNAK, urlValidator.isValid(fileNAK));
-    }
-
-    @Test
-    public void testValidator452(){
-      final UrlValidator urlValidator = new UrlValidator();
-      assertTrue(urlValidator.isValid("http://[::FFFF:129.144.52.38]:80/index.html"));
-    }
-
-    @Test
-    public void testValidator473_1() { // reject null DomainValidator
-        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
-                new UrlValidator(new String[]{}, null, 0L, null));
-        assertThat(thrown.getMessage(), is(equalTo("DomainValidator must not be null")));
-    }
-
-    @Test
-    public void testValidator473_2() { // reject null DomainValidator with mismatched allowLocal
-        final List<DomainValidator.Item> items = new ArrayList<>();
-        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
-                new UrlValidator(new String[]{}, null, 0L, DomainValidator.getInstance(true, items)));
-        assertThat(thrown.getMessage(), is(equalTo("DomainValidator disagrees with ALLOW_LOCAL_URLS setting")));
-    }
-
-    @Test
-    public void testValidator473_3() { // reject null DomainValidator with mismatched allowLocal
-        final List<DomainValidator.Item> items = new ArrayList<>();
-        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () ->
-                new UrlValidator(new String[]{}, null, UrlValidator.ALLOW_LOCAL_URLS, DomainValidator.getInstance(false, items)));
-        assertThat(thrown.getMessage(), is(equalTo("DomainValidator disagrees with ALLOW_LOCAL_URLS setting")));
-    }
-
-    static boolean incrementTestPartsIndex(final int[] testPartsIndex, final Object[] testParts) {
-      boolean carry = true;  //add 1 to lowest order part.
-      boolean maxIndex = true;
-      for (int testPartsIndexIndex = testPartsIndex.length - 1; testPartsIndexIndex >= 0; --testPartsIndexIndex) {
-         int index = testPartsIndex[testPartsIndexIndex];
-         final ResultPair[] part = (ResultPair[]) testParts[testPartsIndexIndex];
-         maxIndex &= (index == (part.length - 1));
-         if (carry) {
-            if (index < part.length - 1) {
-               index++;
-               testPartsIndex[testPartsIndexIndex] = index;
-               carry = false;
-            } else {
-               testPartsIndex[testPartsIndexIndex] = 0;
-               carry = true;
-            }
-         }
-      }
-
-
-      return (!maxIndex);
-   }
-
-   private String testPartsIndextoString() {
-       final StringBuilder carryMsg = new StringBuilder("{");
-      for (int testPartsIndexIndex = 0; testPartsIndexIndex < testPartsIndex.length; ++testPartsIndexIndex) {
-         carryMsg.append(testPartsIndex[testPartsIndexIndex]);
-         if (testPartsIndexIndex < testPartsIndex.length - 1) {
-            carryMsg.append(',');
-         } else {
-            carryMsg.append('}');
-         }
-      }
-      return carryMsg.toString();
-
-   }
-
-   @Test
-   public void testValidateUrl() {
-      assertTrue(true);
-   }
-
-   @Test
-   public void testValidator290() {
+    public void testValidator290() {
         final UrlValidator validator = new UrlValidator();
         assertTrue(validator.isValid("http://xn--h1acbxfam.idn.icann.org/"));
 //        assertTrue(validator.isValid("http://xn--e1afmkfd.xn--80akhbyknj4f"));
         // Internationalized country code top-level domains
-        assertTrue(validator.isValid("http://test.xn--lgbbat1ad8j")); //Algeria
+        assertTrue(validator.isValid("http://test.xn--lgbbat1ad8j")); // Algeria
         assertTrue(validator.isValid("http://test.xn--fiqs8s")); // China
         assertTrue(validator.isValid("http://test.xn--fiqz9s")); // China
         assertTrue(validator.isValid("http://test.xn--wgbh1c")); // Egypt
@@ -453,7 +416,7 @@
         assertTrue(validator.isValid("http://test.xn--ygbi2ammx")); // Palestinian Territory
         assertTrue(validator.isValid("http://test.xn--wgbl6a")); // Qatar
         assertTrue(validator.isValid("http://test.xn--p1ai")); // Russia
-        assertTrue(validator.isValid("http://test.xn--mgberp4a5d4ar")); //  Saudi Arabia
+        assertTrue(validator.isValid("http://test.xn--mgberp4a5d4ar")); // Saudi Arabia
         assertTrue(validator.isValid("http://test.xn--90a3ac")); // Serbia
         assertTrue(validator.isValid("http://test.xn--yfro4i67o")); // Singapore
         assertTrue(validator.isValid("http://test.xn--clchc0ea0b2g2a9gcd")); // Singapore
@@ -488,14 +451,67 @@
 //        assertTrue(validator.isValid("http://test.xn--hlcj6aya9esc7a")); // Tamil
     }
 
-   @Test
-   public void testValidator361() {
-       final UrlValidator validator = new UrlValidator();
-       assertTrue(validator.isValid("http://hello.tokyo/"));
+    @Test
+    public void testValidator309() {
+        UrlValidator urlValidator = new UrlValidator();
+        assertTrue(urlValidator.isValid("http://sample.ondemand.com/"));
+        assertTrue(urlValidator.isValid("hTtP://sample.ondemand.CoM/"));
+        assertTrue(urlValidator.isValid("httpS://SAMPLE.ONEMAND.COM/"));
+        urlValidator = new UrlValidator(new String[] { "HTTP", "HTTPS" });
+        assertTrue(urlValidator.isValid("http://sample.ondemand.com/"));
+        assertTrue(urlValidator.isValid("hTtP://sample.ondemand.CoM/"));
+        assertTrue(urlValidator.isValid("httpS://SAMPLE.ONEMAND.COM/"));
     }
 
-   @Test
-   public void testValidator363(){
+    @Test
+    public void testValidator339() {
+        final UrlValidator urlValidator = new UrlValidator();
+        assertTrue(urlValidator.isValid("http://www.cnn.com/WORLD/?hpt=sitenav")); // without
+        assertTrue(urlValidator.isValid("http://www.cnn.com./WORLD/?hpt=sitenav")); // with
+        assertFalse(urlValidator.isValid("http://www.cnn.com../")); // doubly dotty
+        assertFalse(urlValidator.isValid("http://www.cnn.invalid/"));
+        assertFalse(urlValidator.isValid("http://www.cnn.invalid./")); // check . does not affect invalid domains
+    }
+
+    @Test
+    public void testValidator339IDN() {
+        final UrlValidator urlValidator = new UrlValidator();
+        assertTrue(urlValidator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„/WORLD/?hpt=sitenav")); // without
+        assertTrue(urlValidator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„./WORLD/?hpt=sitenav")); // with
+        assertFalse(urlValidator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„..../")); // very dotty
+        assertFalse(urlValidator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„.../")); // triply dotty
+        assertFalse(urlValidator.isValid("http://ĐŋŅ€ĐĩСидĐĩĐŊŅ‚.Ņ€Ņ„../")); // doubly dotty
+    }
+
+    @Test
+    public void testValidator342() {
+        final UrlValidator urlValidator = new UrlValidator();
+        assertTrue(urlValidator.isValid("http://example.rocks/"));
+        assertTrue(urlValidator.isValid("http://example.rocks"));
+    }
+
+    @Test
+    public void testValidator353() { // userinfo
+        final UrlValidator validator = new UrlValidator();
+        assertTrue(validator.isValid("http://www.apache.org:80/path"));
+        assertTrue(validator.isValid("http://user:pass@www.apache.org:80/path"));
+        assertTrue(validator.isValid("http://user:@www.apache.org:80/path"));
+        assertTrue(validator.isValid("http://user@www.apache.org:80/path"));
+        assertTrue(validator.isValid("http://us%00er:-._~!$&'()*+,;=@www.apache.org:80/path"));
+        assertFalse(validator.isValid("http://:pass@www.apache.org:80/path"));
+        assertFalse(validator.isValid("http://:@www.apache.org:80/path"));
+        assertFalse(validator.isValid("http://user:pa:ss@www.apache.org/path"));
+        assertFalse(validator.isValid("http://user:pa@ss@www.apache.org/path"));
+    }
+
+    @Test
+    public void testValidator361() {
+        final UrlValidator validator = new UrlValidator();
+        assertTrue(validator.isValid("http://hello.tokyo/"));
+    }
+
+    @Test
+    public void testValidator363() {
         final UrlValidator urlValidator = new UrlValidator();
         assertTrue(urlValidator.isValid("http://www.example.org/a/b/hello..world"));
         assertTrue(urlValidator.isValid("http://www.example.org/a/hello..world"));
@@ -515,212 +531,106 @@
         assertTrue(urlValidator.isValid("http://www.example.org/.../.."));
     }
 
-   @Test
-   public void testValidator375() {
-       final UrlValidator validator = new UrlValidator();
-       String url = "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html";
-       assertTrue("IPv6 address URL should validate: " + url, validator.isValid(url));
-       url = "http://[::1]:80/index.html";
-       assertTrue("IPv6 address URL should validate: " + url, validator.isValid(url));
-       url = "http://FEDC:BA98:7654:3210:FEDC:BA98:7654:3210:80/index.html";
-       assertFalse("IPv6 address without [] should not validate: " + url, validator.isValid(url));
+    @Test
+    public void testValidator375() {
+        final UrlValidator validator = new UrlValidator();
+        String url = "http://[FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:80/index.html";
+        assertTrue(validator.isValid(url), "IPv6 address URL should validate: " + url);
+        url = "http://[::1]:80/index.html";
+        assertTrue(validator.isValid(url), "IPv6 address URL should validate: " + url);
+        url = "http://FEDC:BA98:7654:3210:FEDC:BA98:7654:3210:80/index.html";
+        assertFalse(validator.isValid(url), "IPv6 address without [] should not validate: " + url);
     }
 
+    @Test
+    public void testValidator380() {
+        final UrlValidator validator = new UrlValidator();
+        assertTrue(validator.isValid("http://www.apache.org:80/path"));
+        assertTrue(validator.isValid("http://www.apache.org:8/path"));
+        assertTrue(validator.isValid("http://www.apache.org:/path"));
+    }
 
-   @Test
-   public void testValidator353() { // userinfo
-       final UrlValidator validator = new UrlValidator();
-       assertTrue(validator.isValid("http://www.apache.org:80/path"));
-       assertTrue(validator.isValid("http://user:pass@www.apache.org:80/path"));
-       assertTrue(validator.isValid("http://user:@www.apache.org:80/path"));
-       assertTrue(validator.isValid("http://user@www.apache.org:80/path"));
-       assertTrue(validator.isValid("http://us%00er:-._~!$&'()*+,;=@www.apache.org:80/path"));
-       assertFalse(validator.isValid("http://:pass@www.apache.org:80/path"));
-       assertFalse(validator.isValid("http://:@www.apache.org:80/path"));
-       assertFalse(validator.isValid("http://user:pa:ss@www.apache.org/path"));
-       assertFalse(validator.isValid("http://user:pa@ss@www.apache.org/path"));
-   }
+    @Test
+    public void testValidator382() {
+        final UrlValidator validator = new UrlValidator();
+        assertTrue(validator.isValid("ftp://username:password@example.com:8042/over/there/index.dtb?type=animal&name=narwhal#nose"));
+    }
 
-   @Test
-   public void testValidator382() {
-       final UrlValidator validator = new UrlValidator();
-       assertTrue(validator.isValid("ftp://username:password@example.com:8042/over/there/index.dtb?type=animal&name=narwhal#nose"));
-   }
+    @Test
+    public void testValidator391FAILS() {
+        final String[] schemes = { "file" };
+        final UrlValidator urlValidator = new UrlValidator(schemes);
+        assertTrue(urlValidator.isValid("file:/C:/path/to/dir/"));
+    }
 
-   @Test
-   public void testValidator380() {
-       final UrlValidator validator = new UrlValidator();
-       assertTrue(validator.isValid("http://www.apache.org:80/path"));
-       assertTrue(validator.isValid("http://www.apache.org:8/path"));
-       assertTrue(validator.isValid("http://www.apache.org:/path"));
-   }
+    @Test
+    public void testValidator391OK() {
+        final String[] schemes = { "file" };
+        final UrlValidator urlValidator = new UrlValidator(schemes);
+        assertTrue(urlValidator.isValid("file:///C:/path/to/dir/"));
+    }
 
-   @Test
-   public void testValidator420() {
-       final UrlValidator validator = new UrlValidator();
-       assertFalse(validator.isValid("http://example.com/serach?address=Main Avenue"));
-       assertTrue(validator.isValid("http://example.com/serach?address=Main%20Avenue"));
-       assertTrue(validator.isValid("http://example.com/serach?address=Main+Avenue"));
-   }
+    @Test
+    public void testValidator411() {
+        final UrlValidator urlValidator = new UrlValidator();
+        assertTrue(urlValidator.isValid("http://example.rocks:/"));
+        assertTrue(urlValidator.isValid("http://example.rocks:0/"));
+        assertTrue(urlValidator.isValid("http://example.rocks:65535/"));
+        assertFalse(urlValidator.isValid("http://example.rocks:65536/"));
+        assertFalse(urlValidator.isValid("http://example.rocks:100000/"));
+    }
 
-   @Test
-   public void testValidator467() {
-      final UrlValidator validator = new UrlValidator(UrlValidator.ALLOW_2_SLASHES);
-      assertTrue(validator.isValid("https://example.com/some_path/path/"));
-      assertTrue(validator.isValid("https://example.com//somepath/path/"));
-      assertTrue(validator.isValid("https://example.com//some_path/path/"));
-      assertTrue(validator.isValid("http://example.com//_test")); // VALIDATOR-429
-  }
+    @Test
+    public void testValidator420() {
+        final UrlValidator validator = new UrlValidator();
+        assertFalse(validator.isValid("http://example.com/serach?address=Main Avenue"));
+        assertTrue(validator.isValid("http://example.com/serach?address=Main%20Avenue"));
+        assertTrue(validator.isValid("http://example.com/serach?address=Main+Avenue"));
+    }
 
-  @Test
-  public void testValidator283() {
-   final UrlValidator validator = new UrlValidator();
-   assertFalse(validator.isValid("http://finance.yahoo.com/news/Owners-54B-NY-housing-apf-2493139299.html?x=0&ap=%fr"));
-   assertTrue(validator.isValid("http://finance.yahoo.com/news/Owners-54B-NY-housing-apf-2493139299.html?x=0&ap=%22"));
-  }
+    @Test
+    public void testValidator452() {
+        final UrlValidator urlValidator = new UrlValidator();
+        assertTrue(urlValidator.isValid("http://[::FFFF:129.144.52.38]:80/index.html"));
+    }
 
-  @Test
-  public void testFragments() {
-   final String[] schemes = {"http","https"};
-   UrlValidator urlValidator = new UrlValidator(schemes, UrlValidator.NO_FRAGMENTS);
-   assertFalse(urlValidator.isValid("http://apache.org/a/b/c#frag"));
-   urlValidator = new UrlValidator(schemes);
-   assertTrue(urlValidator.isValid("http://apache.org/a/b/c#frag"));
-}
+    @Test
+    public void testValidator464() {
+        final String[] schemes = { "file" };
+        final UrlValidator urlValidator = new UrlValidator(schemes);
+        final String fileNAK = "file://bad ^ domain.com/label/test";
+        assertFalse(urlValidator.isValid(fileNAK), fileNAK);
+    }
 
-  //-------------------- Test data for creating a composite URL
-   /**
-    * The data given below approximates the 4 parts of a URL
-    * <scheme>://<authority><path>?<query> except that the port number
-    * is broken out of authority to increase the number of permutations.
-    * A complete URL is composed of a scheme+authority+port+path+query,
-    * all of which must be individually valid for the entire URL to be considered
-    * valid.
-    */
-   ResultPair[] testUrlScheme = {new ResultPair("http://", true),
-                               new ResultPair("ftp://", true),
-                               new ResultPair("h3t://", true),
-                               new ResultPair("3ht://", false),
-                               new ResultPair("http:/", false),
-                               new ResultPair("http:", false),
-                               new ResultPair("http/", false),
-                               new ResultPair("://", false)};
+    @Test
+    public void testValidator467() {
+        final UrlValidator validator = new UrlValidator(UrlValidator.ALLOW_2_SLASHES);
+        assertTrue(validator.isValid("https://example.com/some_path/path/"));
+        assertTrue(validator.isValid("https://example.com//somepath/path/"));
+        assertTrue(validator.isValid("https://example.com//some_path/path/"));
+        assertTrue(validator.isValid("http://example.com//_test")); // VALIDATOR-429
+    }
 
-   ResultPair[] testUrlAuthority = {new ResultPair("www.google.com", true),
-                                  new ResultPair("www.google.com.", true),
-                                  new ResultPair("go.com", true),
-                                  new ResultPair("go.au", true),
-                                  new ResultPair("0.0.0.0", true),
-                                  new ResultPair("255.255.255.255", true),
-                                  new ResultPair("256.256.256.256", false),
-                                  new ResultPair("255.com", true),
-                                  new ResultPair("1.2.3.4.5", false),
-                                  new ResultPair("1.2.3.4.", false),
-                                  new ResultPair("1.2.3", false),
-                                  new ResultPair(".1.2.3.4", false),
-                                  new ResultPair("go.a", false),
-                                  new ResultPair("go.a1a", false),
-                                  new ResultPair("go.cc", true),
-                                  new ResultPair("go.1aa", false),
-                                  new ResultPair("aaa.", false),
-                                  new ResultPair(".aaa", false),
-                                  new ResultPair("aaa", false),
-                                  new ResultPair("", false)
-   };
-   ResultPair[] testUrlPort = {new ResultPair(":80", true),
-                             new ResultPair(":65535", true), // max possible
-                             new ResultPair(":65536", false), // max possible +1
-                             new ResultPair(":0", true),
-                             new ResultPair("", true),
-                             new ResultPair(":-1", false),
-                             new ResultPair(":65636", false),
-                             new ResultPair(":999999999999999999", false),
-                             new ResultPair(":65a", false)
-   };
-   ResultPair[] testPath = {new ResultPair("/test1", true),
-                          new ResultPair("/t123", true),
-                          new ResultPair("/$23", true),
-                          new ResultPair("/..", false),
-                          new ResultPair("/../", false),
-                          new ResultPair("/test1/", true),
-                          new ResultPair("", true),
-                          new ResultPair("/test1/file", true),
-                          new ResultPair("/..//file", false),
-                          new ResultPair("/test1//file", false)
-   };
-   //Test allow2slash, noFragment
-   ResultPair[] testUrlPathOptions = {new ResultPair("/test1", true),
-                                    new ResultPair("/t123", true),
-                                    new ResultPair("/$23", true),
-                                    new ResultPair("/..", false),
-                                    new ResultPair("/../", false),
-                                    new ResultPair("/test1/", true),
-                                    new ResultPair("/#", false),
-                                    new ResultPair("", true),
-                                    new ResultPair("/test1/file", true),
-                                    new ResultPair("/t123/file", true),
-                                    new ResultPair("/$23/file", true),
-                                    new ResultPair("/../file", false),
-                                    new ResultPair("/..//file", false),
-                                    new ResultPair("/test1//file", true),
-                                    new ResultPair("/#/file", false)
-   };
+    @Test
+    public void testValidator473_1() { // reject null DomainValidator
+        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, () -> new UrlValidator(new String[] {}, null, 0L, null));
+        assertThat(thrown.getMessage(), is(equalTo("DomainValidator must not be null")));
+    }
 
-   ResultPair[] testUrlQuery = {new ResultPair("?action=view", true),
-                              new ResultPair("?action=edit&mode=up", true),
-                              new ResultPair("", true)
-   };
+    @Test
+    public void testValidator473_2() { // reject null DomainValidator with mismatched allowLocal
+        final List<DomainValidator.Item> items = new ArrayList<>();
+        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
+                () -> new UrlValidator(new String[] {}, null, 0L, DomainValidator.getInstance(true, items)));
+        assertThat(thrown.getMessage(), is(equalTo("DomainValidator disagrees with ALLOW_LOCAL_URLS setting")));
+    }
 
-   Object[] testUrlParts = {testUrlScheme, testUrlAuthority, testUrlPort, testPath, testUrlQuery};
-   Object[] testUrlPartsOptions = {testUrlScheme, testUrlAuthority, testUrlPort, testUrlPathOptions, testUrlQuery};
-   int[] testPartsIndex = {0, 0, 0, 0, 0};
-
-   //---------------- Test data for individual url parts ----------------
-   private final String[] schemes = {"http", "gopher", "g0-To+.",
-                                      "not_valid" // TODO this will need to be dropped if the ctor validates schemes
-                                    };
-
-   ResultPair[] testScheme = {new ResultPair("http", true),
-                            new ResultPair("ftp", false),
-                            new ResultPair("httpd", false),
-                            new ResultPair("gopher", true),
-                            new ResultPair("g0-to+.", true),
-                            new ResultPair("not_valid", false), // underscore not allowed
-                            new ResultPair("HtTp", true),
-                            new ResultPair("telnet", false)};
-
-
-    /**
-     * Validator for checking URL parsing
-     * @param args - URLs to validate
-     */
-    public static void main(final String[] args) {
-      final UrlValidator uv = new UrlValidator();
-      for(final String arg: args) {
-          try {
-              URI uri = new URI(arg);
-              uri = uri.normalize();
-              System.out.println(uri.toString());
-              System.out.printf("URI scheme: %s%n", uri.getScheme());
-              System.out.printf("URI scheme specific part: %s%n", uri.getSchemeSpecificPart());
-              System.out.printf("URI raw scheme specific part: %s%n", uri.getRawSchemeSpecificPart());
-              System.out.printf("URI auth: %s%n", uri.getAuthority());
-              System.out.printf("URI raw auth: %s%n", uri.getRawAuthority());
-              System.out.printf("URI userInfo: %s%n", uri.getUserInfo());
-              System.out.printf("URI raw userInfo: %s%n", uri.getRawUserInfo());
-              System.out.printf("URI host: %s%n", uri.getHost());
-              System.out.printf("URI port: %s%n", uri.getPort());
-              System.out.printf("URI path: %s%n", uri.getPath());
-              System.out.printf("URI raw path: %s%n", uri.getRawPath());
-              System.out.printf("URI query: %s%n", uri.getQuery());
-              System.out.printf("URI raw query: %s%n", uri.getRawQuery());
-              System.out.printf("URI fragment: %s%n", uri.getFragment());
-              System.out.printf("URI raw fragment: %s%n", uri.getRawFragment());
-          } catch (final URISyntaxException e) {
-              System.out.println(e.getMessage());
-          }
-          System.out.printf("isValid: %s%n",uv.isValid(arg));
-      }
-   }
+    @Test
+    public void testValidator473_3() { // reject null DomainValidator with mismatched allowLocal
+        final List<DomainValidator.Item> items = new ArrayList<>();
+        final IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class,
+                () -> new UrlValidator(new String[] {}, null, UrlValidator.ALLOW_LOCAL_URLS, DomainValidator.getInstance(false, items)));
+        assertThat(thrown.getMessage(), is(equalTo("DomainValidator disagrees with ALLOW_LOCAL_URLS setting")));
+    }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/ABANumberCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/ABANumberCheckDigitTest.java
index e76c29f..ae3a475 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/ABANumberCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/ABANumberCheckDigitTest.java
@@ -16,37 +16,20 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import org.junit.jupiter.api.BeforeEach;
 
 /**
  * ABA Number Check Digit Test.
- *
- * @since 1.4
  */
 public class ABANumberCheckDigitTest extends AbstractCheckDigitTest {
 
     /**
-     * Constructor
-     * @param name test name
+     * Sets up routine & valid codes.
      */
-    public ABANumberCheckDigitTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set up routine & valid codes.
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = ABANumberCheckDigit.ABAN_CHECK_DIGIT;
-        valid = new String[] {
-                "123456780",
-                "123123123",
-                "011000015",
-                "111000038",
-                "231381116",
-                "121181976"
-                };
+        valid = new String[] { "123456780", "123123123", "011000015", "111000038", "231381116", "121181976" };
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/AbstractCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/AbstractCheckDigitTest.java
index 060cc77..7a9e0c4 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/AbstractCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/AbstractCheckDigitTest.java
@@ -16,6 +16,12 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
+
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.ObjectInputStream;
@@ -25,17 +31,17 @@
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
-
-import junit.framework.TestCase;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * Luhn Check Digit Test.
- *
- * @since 1.4
  */
-public abstract class AbstractCheckDigitTest extends TestCase {
+public abstract class AbstractCheckDigitTest {
 
-    /** logging instance */
+    private static final String POSSIBLE_CHECK_DIGITS = "0123456789 ABCDEFHIJKLMNOPQRSTUVWXYZ\tabcdefghijklmnopqrstuvwxyz!@£$%^&*()_+";
+
+    /** Logging instance */
     protected Log log = LogFactory.getLog(getClass());
 
     /** Check digit routine being tested */
@@ -45,131 +51,95 @@
     protected CheckDigit routine;
 
     /**
-     * Array of valid code values
-     * These must contain valid strings *including* the check digit.
+     * Array of valid code values These must contain valid strings *including* the check digit.
      *
-     * They are passed to:
-     * CheckDigit.isValid(expects string including checkdigit)
-     * which is expected to return true
-     * and
-     * AbstractCheckDigitTest.createInvalidCodes() which
-     * mangles the last character to check that the result is now invalid.
-     * and
-     * the truncated string is passed to
-     * CheckDigit.calculate(expects string without checkdigit)
-     * the result is compared with the last character
+     * They are passed to: CheckDigit.isValid(expects string including checkdigit) which is expected to return true and
+     * AbstractCheckDigitTest.createInvalidCodes() which mangles the last character to check that the result is now invalid. and the truncated string is passed
+     * to CheckDigit.calculate(expects string without checkdigit) the result is compared with the last character
      */
     protected String[] valid;
 
     /**
      * Array of invalid code values
      *
-     * These are currently passed to both
-     * CheckDigit.calculate(expects a string without checkdigit)
-     * which is expected to throw an exception
-     * However that only applies if the string is syntactically incorrect;
-     * and
-     * CheckDigit.isValid(expects a string including checkdigit)
-     * which is expected to return false
+     * These are currently passed to both CheckDigit.calculate(expects a string without checkdigit) which is expected to throw an exception However that only
+     * applies if the string is syntactically incorrect; and CheckDigit.isValid(expects a string including checkdigit) which is expected to return false
      *
      * See https://issues.apache.org/jira/browse/VALIDATOR-344 for some dicussion on this
      */
-    protected String[] invalid = {"12345678A"};
+    protected String[] invalid = { "12345678A" };
 
-    /** code value which sums to zero */
+    /** Code value which sums to zero */
     protected String zeroSum = "0000000000";
 
     /** Prefix for error messages */
     protected String missingMessage = "Code is missing";
 
     /**
-     * Constructor
-     * @param name test name
+     * Returns the check digit (i.e. last character) for a code.
+     *
+     * @param code The code
+     * @return The check digit
      */
-    public AbstractCheckDigitTest(final String name) {
-        super(name);
+    protected String checkDigit(final String code) {
+        if (code == null || code.length() <= checkDigitLth) {
+            return "";
+        }
+        final int start = code.length() - checkDigitLth;
+        return code.substring(start);
+    }
+
+    // private static final String POSSIBLE_CHECK_DIGITS = "0123456789";
+    /**
+     * Returns an array of codes with invalid check digits.
+     *
+     * @param codes Codes with valid check digits
+     * @return Codes with invalid check digits
+     */
+    protected String[] createInvalidCodes(final String[] codes) {
+        final List<String> list = new ArrayList<>();
+
+        // create invalid check digit values
+        for (final String fullCode : codes) {
+            final String code = removeCheckDigit(fullCode);
+            final String check = checkDigit(fullCode);
+            for (int j = 0; j < POSSIBLE_CHECK_DIGITS.length(); j++) {
+                final String curr = POSSIBLE_CHECK_DIGITS.substring(j, j + 1);// "" + Character.forDigit(j, 10);
+                if (!curr.equals(check)) {
+                    list.add(code + curr);
+                }
+            }
+        }
+
+        return list.toArray(new String[0]);
+    }
+
+    /**
+     * Returns a code with the Check Digit (i.e. last character) removed.
+     *
+     * @param code The code
+     * @return The code without the check digit
+     */
+    protected String removeCheckDigit(final String code) {
+        if (code == null || code.length() <= checkDigitLth) {
+            return null;
+        }
+        return code.substring(0, code.length() - checkDigitLth);
     }
 
     /**
      * Tear Down - clears routine and valid codes.
      */
-    @Override
-    protected void tearDown() throws Exception {
-        super.tearDown();
+    @AfterEach
+    protected void tearDown() {
         valid = null;
         routine = null;
     }
 
     /**
-     * Test isValid() for valid values.
-     */
-    public void testIsValidTrue() {
-        if (log.isDebugEnabled()) {
-            log.debug("testIsValidTrue() for " + routine.getClass().getName());
-        }
-
-        // test valid values
-        for (int i = 0; i < valid.length; i++) {
-            if (log.isDebugEnabled()) {
-                log.debug("   " + i + " Testing Valid Code=[" + valid[i] + "]");
-            }
-            assertTrue("valid[" + i +"]: " + valid[i], routine.isValid(valid[i]));
-        }
-    }
-
-    /**
-     * Test isValid() for invalid values.
-     */
-    public void testIsValidFalse() {
-        if (log.isDebugEnabled()) {
-            log.debug("testIsValidFalse() for " + routine.getClass().getName());
-        }
-
-        // test invalid code values
-        for (int i = 0; i < invalid.length; i++) {
-            if (log.isDebugEnabled()) {
-                log.debug("   " + i + " Testing Invalid Code=[" + invalid[i] + "]");
-            }
-            assertFalse("invalid[" + i +"]: " + invalid[i], routine.isValid(invalid[i]));
-        }
-
-        // test invalid check digit values
-        final String[] invalidCheckDigits = createInvalidCodes(valid);
-        for (int i = 0; i < invalidCheckDigits.length; i++) {
-            if (log.isDebugEnabled()) {
-                log.debug("   " + i + " Testing Invalid Check Digit, Code=[" + invalidCheckDigits[i] + "]");
-            }
-            assertFalse("invalid check digit[" + i +"]: " + invalidCheckDigits[i], routine.isValid(invalidCheckDigits[i]));
-        }
-    }
-
-    /**
-     * Test calculate() for valid values.
-     */
-    public void testCalculateValid() {
-        if (log.isDebugEnabled()) {
-            log.debug("testCalculateValid() for " + routine.getClass().getName());
-        }
-
-        // test valid values
-        for (int i = 0; i < valid.length; i++) {
-            final String code = removeCheckDigit(valid[i]);
-            final String expected = checkDigit(valid[i]);
-            try {
-                if (log.isDebugEnabled()) {
-                    log.debug("   " + i + " Testing Valid Check Digit, Code=[" + code + "] expected=[" + expected + "]");
-                }
-                assertEquals("valid[" + i +"]: " + valid[i], expected, routine.calculate(code));
-            } catch (final Exception e) {
-                fail("valid[" + i +"]=" + valid[i] + " threw " + e);
-            }
-        }
-
-    }
-
-    /**
      * Test calculate() for invalid values.
      */
+    @Test
     public void testCalculateInvalid() {
 
         if (log.isDebugEnabled()) {
@@ -194,33 +164,104 @@
                 // Invalid ISBN Length ...
                 // Invalid Character[ ...
                 // Are there any others?
-                assertTrue("Invalid Character[" +i +"]=" +  e.getMessage(), e.getMessage().startsWith("Invalid "));
+                assertTrue(e.getMessage().startsWith("Invalid "), "Invalid Character[" + i + "]=" + e.getMessage());
 // WAS                assertTrue("Invalid Character[" +i +"]=" +  e.getMessage(), e.getMessage().startsWith("Invalid Character["));
             }
         }
     }
 
     /**
+     * Test calculate() for valid values.
+     */
+    @Test
+    public void testCalculateValid() {
+        if (log.isDebugEnabled()) {
+            log.debug("testCalculateValid() for " + routine.getClass().getName());
+        }
+
+        // test valid values
+        for (int i = 0; i < valid.length; i++) {
+            final String code = removeCheckDigit(valid[i]);
+            final String expected = checkDigit(valid[i]);
+            try {
+                if (log.isDebugEnabled()) {
+                    log.debug("   " + i + " Testing Valid Check Digit, Code=[" + code + "] expected=[" + expected + "]");
+                }
+                assertEquals(expected, routine.calculate(code), "valid[" + i + "]: " + valid[i]);
+            } catch (final Exception e) {
+                fail("valid[" + i + "]=" + valid[i] + " threw " + e);
+            }
+        }
+
+    }
+
+    /**
+     * Test isValid() for invalid values.
+     */
+    @Test
+    public void testIsValidFalse() {
+        if (log.isDebugEnabled()) {
+            log.debug("testIsValidFalse() for " + routine.getClass().getName());
+        }
+
+        // test invalid code values
+        for (int i = 0; i < invalid.length; i++) {
+            if (log.isDebugEnabled()) {
+                log.debug("   " + i + " Testing Invalid Code=[" + invalid[i] + "]");
+            }
+            assertFalse(routine.isValid(invalid[i]), "invalid[" + i + "]: " + invalid[i]);
+        }
+
+        // test invalid check digit values
+        final String[] invalidCheckDigits = createInvalidCodes(valid);
+        for (int i = 0; i < invalidCheckDigits.length; i++) {
+            if (log.isDebugEnabled()) {
+                log.debug("   " + i + " Testing Invalid Check Digit, Code=[" + invalidCheckDigits[i] + "]");
+            }
+            assertFalse(routine.isValid(invalidCheckDigits[i]), "invalid check digit[" + i + "]: " + invalidCheckDigits[i]);
+        }
+    }
+
+    /**
+     * Test isValid() for valid values.
+     */
+    @Test
+    public void testIsValidTrue() {
+        if (log.isDebugEnabled()) {
+            log.debug("testIsValidTrue() for " + routine.getClass().getName());
+        }
+
+        // test valid values
+        for (int i = 0; i < valid.length; i++) {
+            if (log.isDebugEnabled()) {
+                log.debug("   " + i + " Testing Valid Code=[" + valid[i] + "]");
+            }
+            assertTrue(routine.isValid(valid[i]), "valid[" + i + "]: " + valid[i]);
+        }
+    }
+
+    /**
      * Test missing code
      */
+    @Test
     public void testMissingCode() {
 
         // isValid() null
-        assertFalse("isValid() Null", routine.isValid(null));
+        assertFalse(routine.isValid(null), "isValid() Null");
 
         // isValid() zero length
-        assertFalse("isValid() Zero Length", routine.isValid(""));
+        assertFalse(routine.isValid(""), "isValid() Zero Length");
 
         // isValid() length 1
         // Don't use 0, because that passes for Verhoef (not sure why yet)
-        assertFalse("isValid() Length 1", routine.isValid("9"));
+        assertFalse(routine.isValid("9"), "isValid() Length 1");
 
         // calculate() null
         try {
             routine.calculate(null);
             fail("calculate() Null - expected exception");
         } catch (final Exception e) {
-            assertEquals("calculate() Null", missingMessage, e.getMessage());
+            assertEquals(missingMessage, e.getMessage(), "calculate() Null");
         }
 
         // calculate() zero length
@@ -228,106 +269,47 @@
             routine.calculate("");
             fail("calculate() Zero Length - expected exception");
         } catch (final Exception e) {
-            assertEquals("calculate() Zero Length",  missingMessage, e.getMessage());
+            assertEquals(missingMessage, e.getMessage(), "calculate() Zero Length");
         }
     }
 
     /**
-     * Test zero sum
-     */
-    public void testZeroSum() {
-
-        assertFalse("isValid() Zero Sum", routine.isValid(zeroSum));
-
-        try {
-            routine.calculate(zeroSum);
-            fail("Zero Sum - expected exception");
-        } catch (final Exception e) {
-            assertEquals("isValid() Zero Sum",  "Invalid code, sum is zero", e.getMessage());
-        }
-
-    }
-
-    /**
      * Test check digit serialization.
      */
+    @Test
     public void testSerialization() {
         // Serialize the check digit routine
         final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        try {
-            final ObjectOutputStream oos = new ObjectOutputStream(baos);
+        try (ObjectOutputStream oos = new ObjectOutputStream(baos)) {
             oos.writeObject(routine);
             oos.flush();
-            oos.close();
         } catch (final Exception e) {
             fail(routine.getClass().getName() + " error during serialization: " + e);
         }
 
         // Deserialize the test object
         Object result = null;
-        try {
-            final ByteArrayInputStream bais =
-                new ByteArrayInputStream(baos.toByteArray());
+        try (ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray())) {
             final ObjectInputStream ois = new ObjectInputStream(bais);
             result = ois.readObject();
-            bais.close();
         } catch (final Exception e) {
             fail(routine.getClass().getName() + " error during deserialization: " + e);
         }
         assertNotNull(result);
     }
 
-    private static final String POSSIBLE_CHECK_DIGITS = "0123456789 ABCDEFHIJKLMNOPQRSTUVWXYZ\tabcdefghijklmnopqrstuvwxyz!@£$%^&*()_+";
-//    private static final String POSSIBLE_CHECK_DIGITS = "0123456789";
     /**
-     * Returns an array of codes with invalid check digits.
-     *
-     * @param codes Codes with valid check digits
-     * @return Codes with invalid check digits
+     * Test zero sum
      */
-    protected String[] createInvalidCodes(final String[] codes) {
-        final List<String> list = new ArrayList<>();
-
-        // create invalid check digit values
-        for (final String fullCode : codes) {
-            final String code = removeCheckDigit(fullCode);
-            final String check = checkDigit(fullCode);
-            for (int j = 0; j < POSSIBLE_CHECK_DIGITS.length(); j++) {
-                final String curr = POSSIBLE_CHECK_DIGITS.substring(j, j + 1);//"" + Character.forDigit(j, 10);
-                if (!curr.equals(check)) {
-                    list.add(code + curr);
-                }
-            }
+    @Test
+    public void testZeroSum() {
+        assertFalse(routine.isValid(zeroSum), "isValid() Zero Sum");
+        try {
+            routine.calculate(zeroSum);
+            fail("Zero Sum - expected exception");
+        } catch (final Exception e) {
+            assertEquals("Invalid code, sum is zero", e.getMessage(), "isValid() Zero Sum");
         }
-
-        return list.toArray(new String[0]);
-    }
-
-    /**
-     * Returns a code with the Check Digit (i.e. last character) removed.
-     *
-     * @param code The code
-     * @return The code without the check digit
-     */
-    protected String removeCheckDigit(final String code) {
-        if (code == null || code.length() <= checkDigitLth) {
-            return null;
-        }
-        return code.substring(0, code.length() - checkDigitLth);
-    }
-
-    /**
-     * Returns the check digit (i.e. last character) for a code.
-     *
-     * @param code The code
-     * @return The check digit
-     */
-    protected String checkDigit(final String code) {
-        if (code == null || code.length() <= checkDigitLth) {
-            return "";
-        }
-        final int start = code.length() - checkDigitLth;
-        return code.substring(start);
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/CUSIPCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/CUSIPCheckDigitTest.java
index 18753e1..0ae3253 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/CUSIPCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/CUSIPCheckDigitTest.java
@@ -16,57 +16,42 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * CUSIP Check Digit Test.
- *
- * @since 1.4
  */
 public class CUSIPCheckDigitTest extends AbstractCheckDigitTest {
 
-    /**
-     * Construct a new test.
-     * @param name test name
-     */
-    public CUSIPCheckDigitTest(final String name) {
-        super(name);
-    }
+    private static final String[] INVALID_CHECK_DIGITS = { "DUS0421CW", "DUS0421CN", "DUS0421CE" };
+
+    private static final String[] VALID_CHECK_DIGITS = { "DUS0421C5" };
 
     /**
-     * Set up routine & valid codes.
+     * Sets up routine & valid codes.
      */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = CUSIPCheckDigit.CUSIP_CHECK_DIGIT;
-        valid = new String[] {"037833100",
-                              "931142103",
-                              "837649128",
-                              "392690QT3",
-                              "594918104",
-                              "86770G101",
-                              "Y8295N109",
-                              "G8572F100"
-                              };
-        invalid = new String[] {"0378#3100"};
+        valid = new String[] { "037833100", "931142103", "837649128", "392690QT3", "594918104", "86770G101", "Y8295N109", "G8572F100" };
+        invalid = new String[] { "0378#3100" };
     }
 
-    private static final String[] INVALID_CHECK_DIGITS = {"DUS0421CW",
-                                                  "DUS0421CN",
-                                                  "DUS0421CE"
-    };
-
+    @Test
     public void testVALIDATOR_336_InvalidCheckDigits() {
         for (final String invalidCheckDigit : INVALID_CHECK_DIGITS) {
-            assertFalse("Should fail: " + invalidCheckDigit, routine.isValid(invalidCheckDigit));
+            assertFalse(routine.isValid(invalidCheckDigit), () -> "Should fail: " + invalidCheckDigit);
         }
     }
 
-    private static final String[] VALID_CHECK_DIGITS = {"DUS0421C5"};
-
+    @Test
     public void testVALIDATOR_336_ValidCheckDigits() {
         for (final String validCheckDigit : VALID_CHECK_DIGITS) {
-            assertTrue("Should fail: " + validCheckDigit, routine.isValid(validCheckDigit));
+            assertTrue(routine.isValid(validCheckDigit), () -> "Should fail: " + validCheckDigit);
         }
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/EAN13CheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/EAN13CheckDigitTest.java
index 47e02fa..289b6e1 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/EAN13CheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/EAN13CheckDigitTest.java
@@ -16,34 +16,20 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import org.junit.jupiter.api.BeforeEach;
 
 /**
  * EAN-13 Check Digit Test.
- *
- * @since 1.4
  */
 public class EAN13CheckDigitTest extends AbstractCheckDigitTest {
 
     /**
-     * Constructor
-     * @param name test name
+     * Sets up routine & valid codes.
      */
-    public EAN13CheckDigitTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set up routine & valid codes.
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = EAN13CheckDigit.EAN13_CHECK_DIGIT;
-        valid = new String[] {
-                "9780072129519",
-                "9780764558313",
-                "4025515373438",
-                "0095673400332"};
+        valid = new String[] { "9780072129519", "9780764558313", "4025515373438", "0095673400332" };
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/IBANCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/IBANCheckDigitTest.java
index d96c8ee..6706963 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/IBANCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/IBANCheckDigitTest.java
@@ -22,165 +22,30 @@
 import java.util.List;
 
 import org.junit.Assert;
-
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * IBAN Check Digit Test.
- *
- * @since 1.4
  */
 public class IBANCheckDigitTest extends AbstractCheckDigitTest {
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public IBANCheckDigitTest(final String name) {
-        super(name);
+    public IBANCheckDigitTest() {
         checkDigitLth = 2;
     }
 
     /**
-     * Set up routine & valid codes.
+     * Returns the check digit (i.e. last character) for a code.
+     *
+     * @param code The code
+     * @return The check digit
      */
     @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        routine = IBANCheckDigit.IBAN_CHECK_DIGIT;
-        valid  = new String[]  {
-                "AD1200012030200359100100",      // Andorra
-                "AE070331234567890123456",       // United Arab Emirates
-                "AL47212110090000000235698741",  // Albania
-                "AT611904300234573201",          // Austria
-                "AZ21NABZ00000000137010001944",  // Azerbaijan
-                "BA391290079401028494",          // Bosnia and Herzegovina
-                "BE62510007547061",              // Belgium
-                "BE68539007547034",              // Belgium
-                "BG80BNBG96611020345678",        // Bulgaria
-                "BH67BMAG00001299123456",        // Bahrain
-                "BI4210000100010000332045181",   // Burundi
-                "BR1800000000141455123924100C2", // Brazil
-                "BY13NBRB3600900000002Z00AB00",  // Belarus
-                "CH3900700115201849173",         // Switzerland
-                "CH9300762011623852957",         // Switzerland
-                "CR05015202001026284066",        // Costa Rica
-                "CY17002001280000001200527600",  // Cyprus
-                "CZ6508000000192000145399",      // Czechoslovakia
-                "DE89370400440532013000",        // Germany
-                "DJ2110002010010409943020008",   // Djibouti
-                "DK5000400440116243",            // Denmark
-                "DO28BAGR00000001212453611324",  // Dominican Republic
-                "EE382200221020145685",          // Estonia
-                "ES8023100001180000012345",      // Spain
-                "FI2112345600000785",            // Finland
-                "FO6264600001631634",            // Denmark (Faroes)
-                "FR1420041010050500013M02606",   // France
-                "GB29NWBK60161331926819",        // UK
-                "GI75NWBK000000007099453",       // Gibraltar
-                "GL8964710001000206",            // Denmark (Greenland)
-                "GR1601101250000000012300695",   // Greece
-                "GT82TRAJ01020000001210029690",  // Guatemala
-                "HR1210010051863000160",         // Croatia
-                "HU42117730161111101800000000",  // Hungary
-                "IE29AIBK93115212345678",        // Ireland
-                "IL620108000000099999999",       // Israel
-                "IQ98NBIQ850123456789012",       // Iraq
-                "IS140159260076545510730339",    // Iceland
-                "IT60X0542811101000000123456",   // Italy
-                "JO94CBJO0010000000000131000302",// Jordan
-                "KW81CBKU0000000000001234560101",// Kuwait
-                "KZ86125KZT5004100100",          // Kazakhstan
-                "LB62099900000001001901229114",  // Lebanon
-                "LC55HEMM000100010012001200023015",//Saint Lucia
-                "LI21088100002324013AA",         // Liechtenstein (Principality of)
-                "LT121000011101001000",          // Lithuania
-                "LU280019400644750000",          // Luxembourg
-                "LV80BANK0000435195001",         // Latvia
-                "MC5811222000010123456789030",   // Monaco
-                "MD24AG000225100013104168",      // Moldova
-                "ME25505000012345678951",        // Montenegro
-                "MK07250120000058984",           // Macedonia, Former Yugoslav Republic of
-                "MR1300020001010000123456753",   // Mauritania
-                "MT84MALT011000012345MTLCAST001S",// Malta
-                "MU17BOMM0101101030300200000MUR",// Mauritius
-                "NL39RABO0300065264",            // Netherlands
-                "NL91ABNA0417164300",            // Netherlands
-                "NO9386011117947",               // Norway
-                "PK36SCBL0000001123456702",      // Pakistan
-                "PL27114020040000300201355387",  // Poland
-                "PL60102010260000042270201111",  // Poland
-                "PS92PALS000000000400123456702", // Palestine, State of
-                "PT50000201231234567890154",     // Portugal
-                "QA58DOHB00001234567890ABCDEFG", // Qatar
-                "RO49AAAA1B31007593840000",      // Romania
-                "RS35260005601001611379",        // Serbia
-                "RU0204452560040702810412345678901",// Russia
-                "SA0380000000608010167519",      // Saudi Arabia
-                "SC18SSCB11010000000000001497USD",// Seychelles
-                "SD8811123456789012",            // Sudan
-                "SE3550000000054910000003",      // Sweden
-                "SD2129010501234001",            // Sudan
-                "SI56191000000123438",           // Slovenia
-                "SK3112000000198742637541",      // Slovak Republic
-                "SM86U0322509800000000270100",   // San Marino
-                "ST68000100010051845310112",     // Sao Tome and Principe
-                "SV62CENR00000000000000700025",  // El Salvador
-                "TL380080012345678910157",       // Timor-Leste
-                "TN5910006035183598478831",      // Tunisia
-                "TR330006100519786457841326",    // Turkey
-                "UA213223130000026007233566001", // Ukraine
-                "VA59001123000012345678",        // Vatican City State
-                "VG96VPVG0000012345678901",      // Virgin Islands, British
-                "XK051212012345678906",          // Republic of Kosovo
-
-                // Codes AA and ZZ will never be used as ISO countries nor in IBANs
-                // add some dummy calculated codes to test the limits
-                // Current minimum length is Norway = 15
-                // Current maximum length is Malta  = 31
-                // N.B. These codes will fail online checkers which validate the IBAN format
-                //234567890123456789012345678901
-                "AA0200000000053",
-                "AA9700000000089",
-                "AA9800000000071",
-                "ZZ02ZZZZZZZZZZZZZZZZZZZZZZZZZ04",
-                "ZZ97ZZZZZZZZZZZZZZZZZZZZZZZZZ40",
-                "ZZ98ZZZZZZZZZZZZZZZZZZZZZZZZZ22",
-                };
-        /*
-         *  sources
-         *  https://intranet.birmingham.ac.uk/finance/documents/public/IBAN.pdf
-         *  http://www.paymentscouncil.org.uk/resources_and_publications/ibans_in_europe/
-         */
-        invalid = new String[] {
-                "510007+47061BE63",
-                "IE01AIBK93118702569045",
-                "AA0000000000089",
-                "AA9900000000053",
-        };
-        zeroSum = null;
-        missingMessage = "Invalid Code length=0";
-
-    }
-
-    /**
-     * Test zero sum
-     */
-    @Override
-    public void testZeroSum() {
-        // ignore, don't run this test
-
-        // example code used to create dummy IBANs
-//        try {
-//            for(int i=0; i<97;i++) {
-//                String check = String.format("ZZ00ZZZZZZZZZZZZZZZZZZZZZZZZZ%02d", new Object[]{Integer.valueOf(i)});
-//                String chk = routine.calculate(check);
-//                if (chk.equals("97")||chk.equals("98")||chk.equals("02")) {
-//                    System.out.println(check+ " "+chk);
-//                }
-//            }
-//        } catch (CheckDigitException e) {
-//            e.printStackTrace();
-//        }
+    protected String checkDigit(final String code) {
+        if (code == null || code.length() <= checkDigitLth) {
+            return "";
+        }
+        return code.substring(2, 4);
     }
 
     /**
@@ -196,9 +61,9 @@
         // create invalid check digit values
         for (final String code2 : codes) {
             final String code = removeCheckDigit(code2);
-            final String check  = checkDigit(code2);
+            final String check = checkDigit(code2);
             for (int j = 2; j <= 98; j++) { // check digits can be from 02-98 (00 and 01 are not possible)
-                final String curr =  j > 9 ? "" + j : "0" + j;
+                final String curr = j > 9 ? "" + j : "0" + j;
                 if (!curr.equals(check)) {
                     list.add(code.substring(0, 2) + curr + code.substring(4));
                 }
@@ -220,25 +85,119 @@
     }
 
     /**
-     * Returns the check digit (i.e. last character) for a code.
-     *
-     * @param code The code
-     * @return The check digit
+     * Sets up routine & valid codes.
      */
-    @Override
-    protected String checkDigit(final String code) {
-        if (code == null || code.length() <= checkDigitLth) {
-            return "";
-        }
-       return code.substring(2, 4);
+    @BeforeEach
+    protected void setUp() {
+        routine = IBANCheckDigit.IBAN_CHECK_DIGIT;
+        valid = new String[] { "AD1200012030200359100100", // Andorra
+                "AE070331234567890123456", // United Arab Emirates
+                "AL47212110090000000235698741", // Albania
+                "AT611904300234573201", // Austria
+                "AZ21NABZ00000000137010001944", // Azerbaijan
+                "BA391290079401028494", // Bosnia and Herzegovina
+                "BE62510007547061", // Belgium
+                "BE68539007547034", // Belgium
+                "BG80BNBG96611020345678", // Bulgaria
+                "BH67BMAG00001299123456", // Bahrain
+                "BI4210000100010000332045181", // Burundi
+                "BR1800000000141455123924100C2", // Brazil
+                "BY13NBRB3600900000002Z00AB00", // Belarus
+                "CH3900700115201849173", // Switzerland
+                "CH9300762011623852957", // Switzerland
+                "CR05015202001026284066", // Costa Rica
+                "CY17002001280000001200527600", // Cyprus
+                "CZ6508000000192000145399", // Czechoslovakia
+                "DE89370400440532013000", // Germany
+                "DJ2110002010010409943020008", // Djibouti
+                "DK5000400440116243", // Denmark
+                "DO28BAGR00000001212453611324", // Dominican Republic
+                "EE382200221020145685", // Estonia
+                "ES8023100001180000012345", // Spain
+                "FI2112345600000785", // Finland
+                "FO6264600001631634", // Denmark (Faroes)
+                "FR1420041010050500013M02606", // France
+                "GB29NWBK60161331926819", // UK
+                "GI75NWBK000000007099453", // Gibraltar
+                "GL8964710001000206", // Denmark (Greenland)
+                "GR1601101250000000012300695", // Greece
+                "GT82TRAJ01020000001210029690", // Guatemala
+                "HR1210010051863000160", // Croatia
+                "HU42117730161111101800000000", // Hungary
+                "IE29AIBK93115212345678", // Ireland
+                "IL620108000000099999999", // Israel
+                "IQ98NBIQ850123456789012", // Iraq
+                "IS140159260076545510730339", // Iceland
+                "IT60X0542811101000000123456", // Italy
+                "JO94CBJO0010000000000131000302", // Jordan
+                "KW81CBKU0000000000001234560101", // Kuwait
+                "KZ86125KZT5004100100", // Kazakhstan
+                "LB62099900000001001901229114", // Lebanon
+                "LC55HEMM000100010012001200023015", // Saint Lucia
+                "LI21088100002324013AA", // Liechtenstein (Principality of)
+                "LT121000011101001000", // Lithuania
+                "LU280019400644750000", // Luxembourg
+                "LV80BANK0000435195001", // Latvia
+                "MC5811222000010123456789030", // Monaco
+                "MD24AG000225100013104168", // Moldova
+                "ME25505000012345678951", // Montenegro
+                "MK07250120000058984", // Macedonia, Former Yugoslav Republic of
+                "MR1300020001010000123456753", // Mauritania
+                "MT84MALT011000012345MTLCAST001S", // Malta
+                "MU17BOMM0101101030300200000MUR", // Mauritius
+                "NL39RABO0300065264", // Netherlands
+                "NL91ABNA0417164300", // Netherlands
+                "NO9386011117947", // Norway
+                "PK36SCBL0000001123456702", // Pakistan
+                "PL27114020040000300201355387", // Poland
+                "PL60102010260000042270201111", // Poland
+                "PS92PALS000000000400123456702", // Palestine, State of
+                "PT50000201231234567890154", // Portugal
+                "QA58DOHB00001234567890ABCDEFG", // Qatar
+                "RO49AAAA1B31007593840000", // Romania
+                "RS35260005601001611379", // Serbia
+                "RU0204452560040702810412345678901", // Russia
+                "SA0380000000608010167519", // Saudi Arabia
+                "SC18SSCB11010000000000001497USD", // Seychelles
+                "SD8811123456789012", // Sudan
+                "SE3550000000054910000003", // Sweden
+                "SD2129010501234001", // Sudan
+                "SI56191000000123438", // Slovenia
+                "SK3112000000198742637541", // Slovak Republic
+                "SM86U0322509800000000270100", // San Marino
+                "ST68000100010051845310112", // Sao Tome and Principe
+                "SV62CENR00000000000000700025", // El Salvador
+                "TL380080012345678910157", // Timor-Leste
+                "TN5910006035183598478831", // Tunisia
+                "TR330006100519786457841326", // Turkey
+                "UA213223130000026007233566001", // Ukraine
+                "VA59001123000012345678", // Vatican City State
+                "VG96VPVG0000012345678901", // Virgin Islands, British
+                "XK051212012345678906", // Republic of Kosovo
+
+                // Codes AA and ZZ will never be used as ISO countries nor in IBANs
+                // add some dummy calculated codes to test the limits
+                // Current minimum length is Norway = 15
+                // Current maximum length is Malta = 31
+                // N.B. These codes will fail online checkers which validate the IBAN format
+                // 234567890123456789012345678901
+                "AA0200000000053", "AA9700000000089", "AA9800000000071", "ZZ02ZZZZZZZZZZZZZZZZZZZZZZZZZ04", "ZZ97ZZZZZZZZZZZZZZZZZZZZZZZZZ40",
+                "ZZ98ZZZZZZZZZZZZZZZZZZZZZZZZZ22", };
+        /*
+         * sources https://intranet.birmingham.ac.uk/finance/documents/public/IBAN.pdf
+         * http://www.paymentscouncil.org.uk/resources_and_publications/ibans_in_europe/
+         */
+        invalid = new String[] { "510007+47061BE63", "IE01AIBK93118702569045", "AA0000000000089", "AA9900000000053", };
+        zeroSum = null;
+        missingMessage = "Invalid Code length=0";
+
     }
 
+    @Test
     public void testOther() throws Exception {
-        try (BufferedReader rdr = new BufferedReader(
-                new InputStreamReader(
-                        this.getClass().getResourceAsStream("IBANtests.txt"),"ASCII"))) {
+        try (BufferedReader rdr = new BufferedReader(new InputStreamReader(this.getClass().getResourceAsStream("IBANtests.txt"), "ASCII"))) {
             String line;
-            while((line=rdr.readLine()) != null) {
+            while ((line = rdr.readLine()) != null) {
                 if (!line.startsWith("#") && !line.isEmpty()) {
                     if (line.startsWith("-")) {
                         line = line.substring(1);
@@ -250,4 +209,26 @@
             }
         }
     }
+
+    /**
+     * Test zero sum
+     */
+    @Override
+    @Test
+    public void testZeroSum() {
+        // ignore, don't run this test
+
+        // example code used to create dummy IBANs
+//        try {
+//            for(int i=0; i<97;i++) {
+//                String check = String.format("ZZ00ZZZZZZZZZZZZZZZZZZZZZZZZZ%02d", new Object[]{Integer.valueOf(i)});
+//                String chk = routine.calculate(check);
+//                if (chk.equals("97")||chk.equals("98")||chk.equals("02")) {
+//                    System.out.println(check+ " "+chk);
+//                }
+//            }
+//        } catch (CheckDigitException e) {
+//            e.printStackTrace();
+//        }
+    }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/ISBN10CheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/ISBN10CheckDigitTest.java
index 9c71f80..22d38b9 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/ISBN10CheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/ISBN10CheckDigitTest.java
@@ -16,35 +16,20 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import org.junit.jupiter.api.BeforeEach;
 
 /**
  * ISBN-10 Check Digit Test.
- *
- * @since 1.4
  */
 public class ISBN10CheckDigitTest extends AbstractCheckDigitTest {
 
     /**
-     * Constructor
-     * @param name test name
+     * Sets up routine & valid codes.
      */
-    public ISBN10CheckDigitTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set up routine & valid codes.
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = ISBN10CheckDigit.ISBN10_CHECK_DIGIT;
-        valid = new String[] {
-                "1930110995",
-                "020163385X",
-                "1932394354",
-                "1590596277"
-                };
+        valid = new String[] { "1930110995", "020163385X", "1932394354", "1590596277" };
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/ISBNCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/ISBNCheckDigitTest.java
index 6fe157b..8d8760c 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/ISBNCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/ISBNCheckDigitTest.java
@@ -16,78 +16,68 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.fail;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * ISBN-10/ISBN-13 Check Digit Test.
- *
- * @since 1.4
  */
 public class ISBNCheckDigitTest extends AbstractCheckDigitTest {
 
     /**
-     * Constructor
-     * @param name test name
+     * Sets up routine & valid codes.
      */
-    public ISBNCheckDigitTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set up routine & valid codes.
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = ISBNCheckDigit.ISBN_CHECK_DIGIT;
-        valid = new String[] {
-                "9780072129519",
-                "9780764558313",
-                "1930110995",
-                "020163385X",
-                "1590596277",    // ISBN-10 Ubuntu Book
-                "9781590596272"  // ISBN-13 Ubuntu Book
-                };
+        valid = new String[] { "9780072129519", "9780764558313", "1930110995", "020163385X", "1590596277", // ISBN-10 Ubuntu Book
+                "9781590596272" // ISBN-13 Ubuntu Book
+        };
         missingMessage = "ISBN Code is missing";
         zeroSum = "000000000000";
     }
 
     /**
-     * Set up routine & valid codes.
+     * Sets up routine & valid codes.
      */
+    @Test
     public void testInvalidLength() {
-        assertFalse("isValid() Lth 9 ", routine.isValid("123456789"));
-        assertFalse("isValid() Lth 11", routine.isValid("12345678901"));
-        assertFalse("isValid() Lth 12", routine.isValid("123456789012"));
-        assertFalse("isValid() Lth 14", routine.isValid("12345678901234"));
+        assertFalse(routine.isValid("123456789"), "isValid() Lth 9 ");
+        assertFalse(routine.isValid("12345678901"), "isValid() Lth 11");
+        assertFalse(routine.isValid("123456789012"), "isValid() Lth 12");
+        assertFalse(routine.isValid("12345678901234"), "isValid() Lth 14");
 
         try {
             routine.calculate("12345678");
             fail("calculate() Lth 8 - expected exception");
         } catch (final Exception e) {
-            assertEquals("calculate() Lth 8", "Invalid ISBN Length = 8", e.getMessage());
+            assertEquals(e.getMessage(), "Invalid ISBN Length = 8", "calculate() Lth 8");
         }
 
         try {
             routine.calculate("1234567890");
             fail("calculate() Lth 10 - expected exception");
         } catch (final Exception e) {
-            assertEquals("calculate() Lth 10", "Invalid ISBN Length = 10", e.getMessage());
+            assertEquals("Invalid ISBN Length = 10", e.getMessage(), "calculate() Lth 10");
         }
 
         try {
             routine.calculate("12345678901");
             fail("calculate() Lth 11 - expected exception");
         } catch (final Exception e) {
-            assertEquals("calculate() Lth 11", "Invalid ISBN Length = 11", e.getMessage());
+            assertEquals("Invalid ISBN Length = 11", e.getMessage(), "calculate() Lth 11");
         }
 
         try {
             routine.calculate("1234567890123");
             fail("calculate() Lth 13 - expected exception");
         } catch (final Exception e) {
-            assertEquals("calculate() Lth 13", "Invalid ISBN Length = 13", e.getMessage());
+            assertEquals("Invalid ISBN Length = 13", e.getMessage(), "calculate() Lth 13");
         }
     }
 
-
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/ISINCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/ISINCheckDigitTest.java
index a113964..90577b8 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/ISINCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/ISINCheckDigitTest.java
@@ -16,57 +16,45 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * ISIN Check Digit Test.
- *
- * @since 1.4
  */
 public class ISINCheckDigitTest extends AbstractCheckDigitTest {
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public ISINCheckDigitTest(final String name) {
-        super(name);
-    }
+    private static final String[] INVALID_CHECK_DIGITS = { "US037833100O", // proper check digit is '5', see above
+            "BMG8571G109D", // proper check digit is '6', see above
+            "AU0000XVGZAD", // proper check digit is '3', see above
+            "GB000263494I", // proper check digit is '6', see above
+            "FR000402625C", // proper check digit is '0', see above
+            "DK000976334H", // proper check digit is '4', see above
+    };
 
     /**
-     * Set up routine & valid codes.
+     * Sets up routine & valid codes.
      */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = ISINCheckDigit.ISIN_CHECK_DIGIT;
-        valid = new String[] {"US0378331005",
-                              "BMG8571G1096",
-                              "AU0000XVGZA3",
-                              "GB0002634946",
-                              "FR0004026250",
-                                "3133EHHF3", // see VALIDATOR-422 Valid check-digit, but not valid ISIN
-                              "DK0009763344",
-                              "dk0009763344", // TODO lowercase is currently accepted, but is this valid?
-                              "AU0000xvgza3", // lowercase NSIN
-                              "EZ0000000003", // Invented; for use in ISINValidatorTest
-                              "XS0000000009", // ditto
-                              "AA0000000006", // ditto
-                              };
-        invalid = new String[] {"0378#3100"};
+        valid = new String[] { "US0378331005", "BMG8571G1096", "AU0000XVGZA3", "GB0002634946", "FR0004026250", "3133EHHF3", // see VALIDATOR-422 Valid
+                                                                                                                            // check-digit, but not valid ISIN
+                "DK0009763344", "dk0009763344", // TODO lowercase is currently accepted, but is this valid?
+                "AU0000xvgza3", // lowercase NSIN
+                "EZ0000000003", // Invented; for use in ISINValidatorTest
+                "XS0000000009", // ditto
+                "AA0000000006", // ditto
+        };
+        invalid = new String[] { "0378#3100" };
     }
 
-    private static final String[] INVALID_CHECK_DIGITS =
-                             {"US037833100O", // proper check digit is '5', see above
-                              "BMG8571G109D", // proper check digit is '6', see above
-                              "AU0000XVGZAD", // proper check digit is '3', see above
-                              "GB000263494I", // proper check digit is '6', see above
-                              "FR000402625C", // proper check digit is '0', see above
-                              "DK000976334H", // proper check digit is '4', see above
-                              };
-
+    @Test
     public void testVALIDATOR_345() {
         for (final String invalidCheckDigit : INVALID_CHECK_DIGITS) {
-            assertFalse("Should fail: " + invalidCheckDigit, routine.isValid(invalidCheckDigit));
+            assertFalse(routine.isValid(invalidCheckDigit), () -> "Should fail: " + invalidCheckDigit);
         }
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/ISSNCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/ISSNCheckDigitTest.java
index 74ff85d..4cd7a35 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/ISSNCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/ISSNCheckDigitTest.java
@@ -16,50 +16,24 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import org.junit.jupiter.api.BeforeEach;
 
 /**
  * ISSN Check Digit Test.
- *
- * @since 1.5.0
  */
 public class ISSNCheckDigitTest extends AbstractCheckDigitTest {
 
     /**
-     * Constructor
-     * @param name test name
+     * Sets up routine & valid codes.
      */
-    public ISSNCheckDigitTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set up routine & valid codes.
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = ISSNCheckDigit.ISSN_CHECK_DIGIT;
-        valid = new String[] {
-                "03178471",
-                "1050124X",
-                "15626865",
-                "10637710",
-                "17487188",
-                "02642875",
-                "17500095",
-                "11881534",
-                "19111479",
-                "19111460",
-                "00016772",
-                "1365201X",
-                };
-        invalid = new String[] {
-                "03178472", // wrong check
+        valid = new String[] { "03178471", "1050124X", "15626865", "10637710", "17487188", "02642875", "17500095", "11881534", "19111479", "19111460",
+                "00016772", "1365201X", };
+        invalid = new String[] { "03178472", // wrong check
                 "1050-124X", // format char
-                " 1365201X",
-                "1365201X ",
-                " 1365201X ",
-        };
+                " 1365201X", "1365201X ", " 1365201X ", };
         missingMessage = "Code is missing";
         zeroSum = "00000000";
     }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/LuhnCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/LuhnCheckDigitTest.java
index a6f24cf..360d167 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/LuhnCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/LuhnCheckDigitTest.java
@@ -16,44 +16,28 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import org.junit.jupiter.api.BeforeEach;
 
 /**
  * Luhn Check Digit Test.
- *
- * @since 1.4
  */
 public class LuhnCheckDigitTest extends AbstractCheckDigitTest {
 
-    private static final String VALID_VISA       = "4417123456789113";
+    private static final String VALID_VISA = "4417123456789113";
     private static final String VALID_SHORT_VISA = "4222222222222";
-    private static final String VALID_AMEX       = "378282246310005";
+    private static final String VALID_AMEX = "378282246310005";
     private static final String VALID_MASTERCARD = "5105105105105100";
-    private static final String VALID_DISCOVER   = "6011000990139424";
-    private static final String VALID_DINERS     = "30569309025904";
+    private static final String VALID_DISCOVER = "6011000990139424";
+    private static final String VALID_DINERS = "30569309025904";
 
     /**
-     * Constructor
-     * @param name test name
+     * Sets up routine & valid codes.
      */
-    public LuhnCheckDigitTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set up routine & valid codes.
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
 
         routine = LuhnCheckDigit.LUHN_CHECK_DIGIT;
 
-        valid = new String[] {
-                VALID_VISA,
-                VALID_SHORT_VISA,
-                VALID_AMEX,
-                VALID_MASTERCARD,
-                VALID_DISCOVER,
-                VALID_DINERS};
+        valid = new String[] { VALID_VISA, VALID_SHORT_VISA, VALID_AMEX, VALID_MASTERCARD, VALID_DISCOVER, VALID_DINERS };
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenABACheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenABACheckDigitTest.java
index 1496f72..1e630a5 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenABACheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenABACheckDigitTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import org.junit.jupiter.api.BeforeEach;
 
 /**
  * ModulusTenCheckDigit ABA Number Check Digit Test.
@@ -23,28 +24,12 @@
 public class ModulusTenABACheckDigitTest extends AbstractCheckDigitTest {
 
     /**
-     * Constructor
-     * @param name test name
+     * Sets up routine & valid codes.
      */
-    public ModulusTenABACheckDigitTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set up routine & valid codes.
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = new ModulusTenCheckDigit(new int[] { 1, 7, 3 }, true);
-        valid = new String[] {
-                "123456780",
-                "123123123",
-                "011000015",
-                "111000038",
-                "231381116",
-                "121181976"
-                };
+        valid = new String[] { "123456780", "123123123", "011000015", "111000038", "231381116", "121181976" };
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenCUSIPCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenCUSIPCheckDigitTest.java
index 1344d14..1240579 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenCUSIPCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenCUSIPCheckDigitTest.java
@@ -16,55 +16,42 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * ModulusTenCheckDigit CUSIP Test.
  */
 public class ModulusTenCUSIPCheckDigitTest extends AbstractCheckDigitTest {
 
-    /**
-     * Construct a new test.
-     * @param name test name
-     */
-    public ModulusTenCUSIPCheckDigitTest(final String name) {
-        super(name);
-    }
+    private static final String[] INVALID_CHECK_DIGITS = { "DUS0421CW", "DUS0421CN", "DUS0421CE" };
+
+    private static final String[] VALID_CHECK_DIGITS = { "DUS0421C5" };
 
     /**
-     * Set up routine & valid codes.
+     * Sets up routine & valid codes.
      */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-        routine = new ModulusTenCheckDigit(new int[] { 1, 2}, true, true);
-        valid = new String[] {"037833100",
-                              "931142103",
-                              "837649128",
-                              "392690QT3",
-                              "594918104",
-                              "86770G101",
-                              "Y8295N109",
-                              "G8572F100"
-                              };
-        invalid = new String[] {"0378#3100"};
+    @BeforeEach
+    protected void setUp() {
+        routine = new ModulusTenCheckDigit(new int[] { 1, 2 }, true, true);
+        valid = new String[] { "037833100", "931142103", "837649128", "392690QT3", "594918104", "86770G101", "Y8295N109", "G8572F100" };
+        invalid = new String[] { "0378#3100" };
     }
 
-    private static final String[] INVALID_CHECK_DIGITS = {"DUS0421CW",
-                                                  "DUS0421CN",
-                                                  "DUS0421CE"
-    };
-
+    @Test
     public void testVALIDATOR_336_InvalidCheckDigits() {
         for (final String invalidCheckDigit : INVALID_CHECK_DIGITS) {
-            assertFalse("Should fail: " + invalidCheckDigit, routine.isValid(invalidCheckDigit));
+            assertFalse(routine.isValid(invalidCheckDigit), () -> "Should fail: " + invalidCheckDigit);
         }
     }
 
-    private static final String[] VALID_CHECK_DIGITS = {"DUS0421C5"};
-
+    @Test
     public void testVALIDATOR_336_ValidCheckDigits() {
         for (final String validCheckDigit : VALID_CHECK_DIGITS) {
-            assertTrue("Should fail: " + validCheckDigit, routine.isValid(validCheckDigit));
+            assertTrue(routine.isValid(validCheckDigit), () -> "Should fail: " + validCheckDigit);
         }
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenEAN13CheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenEAN13CheckDigitTest.java
index 50f4d6e..c606965 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenEAN13CheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenEAN13CheckDigitTest.java
@@ -16,6 +16,7 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import org.junit.jupiter.api.BeforeEach;
 
 /**
  * ModulusTenCheckDigit EAN-13 Test.
@@ -23,25 +24,12 @@
 public class ModulusTenEAN13CheckDigitTest extends AbstractCheckDigitTest {
 
     /**
-     * Constructor
-     * @param name test name
+     * Sets up routine & valid codes.
      */
-    public ModulusTenEAN13CheckDigitTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set up routine & valid codes.
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = new ModulusTenCheckDigit(new int[] { 1, 3 }, true);
-        valid = new String[] {
-                "9780072129519",
-                "9780764558313",
-                "4025515373438",
-                "0095673400332"};
+        valid = new String[] { "9780072129519", "9780764558313", "4025515373438", "0095673400332" };
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenLuhnCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenLuhnCheckDigitTest.java
index f21bbfe..cf74034 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenLuhnCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenLuhnCheckDigitTest.java
@@ -16,42 +16,27 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import org.junit.jupiter.api.BeforeEach;
 
 /**
  * ModulusTenCheckDigit Luhn Test.
  */
 public class ModulusTenLuhnCheckDigitTest extends AbstractCheckDigitTest {
 
-    private static final String VALID_VISA       = "4417123456789113";
+    private static final String VALID_VISA = "4417123456789113";
     private static final String VALID_SHORT_VISA = "4222222222222";
-    private static final String VALID_AMEX       = "378282246310005";
+    private static final String VALID_AMEX = "378282246310005";
     private static final String VALID_MASTERCARD = "5105105105105100";
-    private static final String VALID_DISCOVER   = "6011000990139424";
-    private static final String VALID_DINERS     = "30569309025904";
+    private static final String VALID_DISCOVER = "6011000990139424";
+    private static final String VALID_DINERS = "30569309025904";
 
     /**
-     * Constructor
-     * @param name test name
+     * Sets up routine & valid codes.
      */
-    public ModulusTenLuhnCheckDigitTest(final String name) {
-        super(name);
-    }
+    @BeforeEach
+    protected void setUp() {
+        routine = new ModulusTenCheckDigit(new int[] { 1, 2 }, true, true);
 
-    /**
-     * Set up routine & valid codes.
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
-
-        routine = new ModulusTenCheckDigit(new int[] {1, 2}, true, true);
-
-        valid = new String[] {
-                VALID_VISA,
-                VALID_SHORT_VISA,
-                VALID_AMEX,
-                VALID_MASTERCARD,
-                VALID_DISCOVER,
-                VALID_DINERS};
+        valid = new String[] { VALID_VISA, VALID_SHORT_VISA, VALID_AMEX, VALID_MASTERCARD, VALID_DISCOVER, VALID_DINERS };
     }
 }
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenSedolCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenSedolCheckDigitTest.java
index 4e4e2ae..9db5f74 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenSedolCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/ModulusTenSedolCheckDigitTest.java
@@ -16,49 +16,38 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * ModulusTenCheckDigit SEDOL Test.
  */
 public class ModulusTenSedolCheckDigitTest extends AbstractCheckDigitTest {
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public ModulusTenSedolCheckDigitTest(final String name) {
-        super(name);
-    }
+    private static final String[] INVALID_CHECK_DIGITS = { "026349E", // proper check digit is '4', see above
+            "087061C", // proper check digit is '2', see above
+            "B06LQ9H", // proper check digit is '7', see above
+            "343757F", // proper check digit is '5', see above
+            "B07LF5F", // proper check digit is '5', see above
+    };
 
     /**
-     * Set up routine & valid codes.
+     * Sets up routine & valid codes.
      */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = new ModulusTenCheckDigit(new int[] { 1, 3, 1, 7, 3, 9, 1 });
-        valid = new String[] {
-                "0263494",
-                "0870612",
-                "B06LQ97",
-                "3437575",
-                "B07LF55",
-                };
-        invalid = new String[] {"123#567"};
+        valid = new String[] { "0263494", "0870612", "B06LQ97", "3437575", "B07LF55", };
+        invalid = new String[] { "123#567" };
         zeroSum = "0000000";
     }
 
-    private static final String[] INVALID_CHECK_DIGITS = {
-                "026349E", // proper check digit is '4', see above
-                "087061C", // proper check digit is '2', see above
-                "B06LQ9H", // proper check digit is '7', see above
-                "343757F", // proper check digit is '5', see above
-                "B07LF5F", // proper check digit is '5', see above
-               };
-
+    @Test
     public void testVALIDATOR_346() {
         for (final String invalidCheckDigit : INVALID_CHECK_DIGITS) {
-            assertFalse("Should fail: " + invalidCheckDigit, routine.isValid(invalidCheckDigit));
+            assertFalse(routine.isValid(invalidCheckDigit), () -> "Should fail: " + invalidCheckDigit);
         }
     }
 
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/SedolCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/SedolCheckDigitTest.java
index 71b377f..9c3a48d 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/SedolCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/SedolCheckDigitTest.java
@@ -16,51 +16,38 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import static org.junit.jupiter.api.Assertions.assertFalse;
+
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
 
 /**
  * ISIN Check Digit Test.
- *
- * @since 1.4
  */
 public class SedolCheckDigitTest extends AbstractCheckDigitTest {
 
-    /**
-     * Constructor
-     * @param name test name
-     */
-    public SedolCheckDigitTest(final String name) {
-        super(name);
-    }
+    private static final String[] INVALID_CHECK_DIGITS = { "026349E", // proper check digit is '4', see above
+            "087061C", // proper check digit is '2', see above
+            "B06LQ9H", // proper check digit is '7', see above
+            "343757F", // proper check digit is '5', see above
+            "B07LF5F", // proper check digit is '5', see above
+    };
 
     /**
-     * Set up routine & valid codes.
+     * Sets up routine & valid codes.
      */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = SedolCheckDigit.SEDOL_CHECK_DIGIT;
-        valid = new String[] {
-                "0263494",
-                "0870612",
-                "B06LQ97",
-                "3437575",
-                "B07LF55",
-                };
-        invalid = new String[] {"123#567"};
+        valid = new String[] { "0263494", "0870612", "B06LQ97", "3437575", "B07LF55", };
+        invalid = new String[] { "123#567" };
         zeroSum = "0000000";
     }
 
-    private static final String[] INVALID_CHECK_DIGITS = {
-                "026349E", // proper check digit is '4', see above
-                "087061C", // proper check digit is '2', see above
-                "B06LQ9H", // proper check digit is '7', see above
-                "343757F", // proper check digit is '5', see above
-                "B07LF5F", // proper check digit is '5', see above
-               };
-
+    @Test
     public void testVALIDATOR_346() {
         for (final String invalidCheckDigit : INVALID_CHECK_DIGITS) {
-            assertFalse("Should fail: " + invalidCheckDigit, routine.isValid(invalidCheckDigit));
+            assertFalse(routine.isValid(invalidCheckDigit), () -> "Should fail: " + invalidCheckDigit);
         }
     }
 
diff --git a/src/test/java/org/apache/commons/validator/routines/checkdigit/VerhoeffCheckDigitTest.java b/src/test/java/org/apache/commons/validator/routines/checkdigit/VerhoeffCheckDigitTest.java
index ba4c9da..75afd95 100644
--- a/src/test/java/org/apache/commons/validator/routines/checkdigit/VerhoeffCheckDigitTest.java
+++ b/src/test/java/org/apache/commons/validator/routines/checkdigit/VerhoeffCheckDigitTest.java
@@ -16,39 +16,28 @@
  */
 package org.apache.commons.validator.routines.checkdigit;
 
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
 /**
  * Verhoeff Check Digit Test.
- *
- * @since 1.4
  */
 public class VerhoeffCheckDigitTest extends AbstractCheckDigitTest {
 
     /**
-     * Construct a new test.
-     * @param name test name
+     * Sets up routine & valid codes.
      */
-    public VerhoeffCheckDigitTest(final String name) {
-        super(name);
-    }
-
-    /**
-     * Set up routine & valid codes.
-     */
-    @Override
-    protected void setUp() throws Exception {
-        super.setUp();
+    @BeforeEach
+    protected void setUp() {
         routine = VerhoeffCheckDigit.VERHOEFF_CHECK_DIGIT;
-        valid = new String[] {
-                "15",
-                "1428570",
-                "12345678902"
-                };
+        valid = new String[] { "15", "1428570", "12345678902" };
     }
 
     /**
      * Test zero sum
      */
     @Override
+    @Test
     public void testZeroSum() {
         // ignore, don't run this test
     }
diff --git a/src/test/java/org/apache/commons/validator/util/FlagsTest.java b/src/test/java/org/apache/commons/validator/util/FlagsTest.java
index f579da4..adc47f9 100644
--- a/src/test/java/org/apache/commons/validator/util/FlagsTest.java
+++ b/src/test/java/org/apache/commons/validator/util/FlagsTest.java
@@ -16,12 +16,16 @@
  */
 package org.apache.commons.validator.util;
 
-import junit.framework.TestCase;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.Test;
 
 /**
  * Test the Flags class.
  */
-public class FlagsTest extends TestCase {
+public class FlagsTest {
 
     /**
      * Declare some flags for testing.
@@ -30,23 +34,56 @@
     private static final long LONG_FLAG_2 = 2;
     private static final int INT_FLAG = 4;
 
+    @Test
+    public void testClear() {
+        final Flags f = new Flags(98432);
+        f.clear();
+        assertEquals(0, f.getFlags());
+    }
+
     /**
-     * Constructor for FlagsTest.
+     * Test for Object clone()
      */
-    public FlagsTest(final String name) {
-        super(name);
+    @Test
+    public void testClone() {
     }
 
-    public void testHashCode() {
-        final Flags f = new Flags(45);
-        assertEquals(f.hashCode(), 45);
+    /**
+     * Test for boolean equals(Object)
+     */
+    @Test
+    public void testEqualsObject() {
     }
 
+    @Test
     public void testGetFlags() {
         final Flags f = new Flags(45);
         assertEquals(f.getFlags(), 45);
     }
 
+    @Test
+    public void testHashCode() {
+        final Flags f = new Flags(45);
+        assertEquals(f.hashCode(), 45);
+    }
+
+    @Test
+    public void testIsOn_isFalseWhenNotAllFlagsInArgumentAreOn() {
+        final Flags first = new Flags(1);
+        final long firstAndSecond = 3;
+
+        assertFalse(first.isOn(firstAndSecond));
+    }
+
+    @Test
+    public void testIsOn_isTrueWhenHighOrderBitIsSetAndQueried() {
+        final Flags allOn = new Flags(~0);
+        final long highOrderBit = 0x8000000000000000L;
+
+        assertTrue(allOn.isOn(highOrderBit));
+    }
+
+    @Test
     public void testIsOnOff() {
         final Flags f = new Flags();
         f.turnOn(LONG_FLAG);
@@ -60,59 +97,10 @@
         assertTrue(f.isOff(LONG_FLAG_2));
     }
 
-    public void testTurnOnOff() {
-    }
-
-    public void testTurnOff() {
-    }
-
-    public void testTurnOffAll() {
-        final Flags f = new Flags(98432);
-        f.turnOffAll();
-        assertEquals(0, f.getFlags());
-    }
-
-    public void testClear() {
-        final Flags f = new Flags(98432);
-        f.clear();
-        assertEquals(0, f.getFlags());
-    }
-
-    public void testTurnOnAll() {
-        final Flags f = new Flags();
-        f.turnOnAll();
-        assertEquals(~0, f.getFlags());
-    }
-
-    public void testIsOn_isFalseWhenNotAllFlagsInArgumentAreOn() {
-        final Flags first = new Flags(1);
-        final long firstAndSecond = 3;
-
-        assertFalse(first.isOn(firstAndSecond));
-    }
-
-    public void testIsOn_isTrueWhenHighOrderBitIsSetAndQueried() {
-        final Flags allOn = new Flags(~0);
-        final long highOrderBit = 0x8000000000000000L;
-
-        assertTrue(allOn.isOn(highOrderBit));
-    }
-
-    /**
-     * Test for Object clone()
-     */
-    public void testClone() {
-    }
-
-    /**
-     * Test for boolean equals(Object)
-     */
-    public void testEqualsObject() {
-    }
-
     /**
      * Test for String toString()
      */
+    @Test
     public void testToString() {
         final Flags f = new Flags();
         String s = f.toString();
@@ -122,9 +110,29 @@
         s = f.toString();
         assertEquals(64, s.length());
 
-        assertEquals(
-            "0000000000000000000000000000000000000000000000000000000000000100",
-            s);
+        assertEquals("0000000000000000000000000000000000000000000000000000000000000100", s);
+    }
+
+    @Test
+    public void testTurnOff() {
+    }
+
+    @Test
+    public void testTurnOffAll() {
+        final Flags f = new Flags(98432);
+        f.turnOffAll();
+        assertEquals(0, f.getFlags());
+    }
+
+    @Test
+    public void testTurnOnAll() {
+        final Flags f = new Flags();
+        f.turnOnAll();
+        assertEquals(~0, f.getFlags());
+    }
+
+    @Test
+    public void testTurnOnOff() {
     }
 
 }
diff --git a/src/test/java/org/apache/commons/validator/util/ValidatorUtilsTest.java b/src/test/java/org/apache/commons/validator/util/ValidatorUtilsTest.java
new file mode 100644
index 0000000..d64414f
--- /dev/null
+++ b/src/test/java/org/apache/commons/validator/util/ValidatorUtilsTest.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.commons.validator.util;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.apache.commons.collections.FastHashMap;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests {@link ValidatorUtilsTest}.
+ */
+public class ValidatorUtilsTest {
+    
+    @Test
+    public void testCopyFastHashMap() {
+        final FastHashMap original = new FastHashMap();
+        original.put("key1", "value1");
+        original.put("key2", "value2");
+        original.put("key3", "value3");
+        original.setFast(true);
+        final FastHashMap copy = ValidatorUtils.copyFastHashMap(original);
+        assertEquals(original, copy);
+      }
+
+}