Repository: xlate/staedi
Pull request #427 (2023-12-30 22:47:23)

Replace singleton validators with EnumMaps of instances

sonarcloud[bot]: ## [![Quality Gate Passed](https://sonarsource.github.io/sonarcloud-github-static-resources/v2/checks/QualityGateBadge/qg-passed-20px.png 'Quality Gate Passed')](https://sonarcloud.io/dashboard?id=xlate_staedi&pullRequest=427) **Quality Gate passed**  
Kudos, no new issues were introduced!

[0 New issues](https://sonarcloud.io/project/issues?id=xlate_staedi&pullRequest=427&resolved=false&inNewCodePeriod=true)  
[0 Security Hotspots](https://sonarcloud.io/project/security_hotspots?id=xlate_staedi&pullRequest=427&resolved=false&inNewCodePeriod=true)  
[100.0% Coverage on New Code](https://sonarcloud.io/component_measures?id=xlate_staedi&pullRequest=427&metric=new_coverage&view=list)  
[0.0% Duplication on New Code](https://sonarcloud.io/component_measures?id=xlate_staedi&pullRequest=427&metric=new_duplicated_lines_density&view=list)  
  
[See analysis details on SonarCloud](https://sonarcloud.io/dashboard?id=xlate_staedi&pullRequest=427)



Patch:
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/AlphaNumericValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/AlphaNumericValidator.java
index f94a8b8..c20e47c 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/AlphaNumericValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/AlphaNumericValidator.java
@@ -25,15 +25,6 @@ import io.xlate.edi.stream.EDIStreamValidationError;
 
 class AlphaNumericValidator extends ElementValidator {
 
-    private static final AlphaNumericValidator singleton = new AlphaNumericValidator();
-
-    private AlphaNumericValidator() {
-    }
-
-    static AlphaNumericValidator getInstance() {
-        return singleton;
-    }
-
     @Override
     void validate(Dialect dialect,
                   EDISimpleType element,
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/ConditionSyntaxValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/ConditionSyntaxValidator.java
index 7c4fe8f..1d8ac68 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/ConditionSyntaxValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/ConditionSyntaxValidator.java
@@ -20,11 +20,6 @@ import io.xlate.edi.schema.EDISyntaxRule;
 
 class ConditionSyntaxValidator implements SyntaxValidator {
 
-    static final ConditionSyntaxValidator INSTANCE = new ConditionSyntaxValidator();
-
-    private ConditionSyntaxValidator() {
-    }
-
     @Override
     public void validate(EDISyntaxRule syntax, UsageNode structure, ValidationEventHandler handler, SyntaxStatus status) {
         if (status.anchorPresent && status.elementCount < syntax.getPositions().size()) {
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/DateValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/DateValidator.java
index c22f8c2..39ec0dc 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/DateValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/DateValidator.java
@@ -24,15 +24,6 @@ import io.xlate.edi.stream.EDIStreamValidationError;
 
 class DateValidator extends ElementValidator {
 
-    private static final DateValidator singleton = new DateValidator();
-
-    private DateValidator() {
-    }
-
-    static DateValidator getInstance() {
-        return singleton;
-    }
-
     @Override
     void validate(Dialect dialect,
                   EDISimpleType element,
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/DecimalValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/DecimalValidator.java
index 5221e36..e219a83 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/DecimalValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/DecimalValidator.java
@@ -19,15 +19,6 @@ import io.xlate.edi.internal.stream.tokenization.Dialect;
 
 class DecimalValidator extends NumericValidator {
 
-    private static final DecimalValidator singleton = new DecimalValidator();
-
-    private DecimalValidator() {
-    }
-
-    static DecimalValidator getInstance() {
-        return singleton;
-    }
-
     @Override
     int validate(Dialect dialect, CharSequence value) {
         int length = value.length();
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/ElementValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/ElementValidator.java
index e6b2535..6fdd33e 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/ElementValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/ElementValidator.java
@@ -15,7 +15,9 @@
  ******************************************************************************/
 package io.xlate.edi.internal.stream.validation;
 
+import java.util.EnumMap;
 import java.util.List;
+import java.util.Map;
 
 import io.xlate.edi.internal.stream.tokenization.Dialect;
 import io.xlate.edi.schema.EDISimpleType;
@@ -23,33 +25,24 @@ import io.xlate.edi.stream.EDIStreamValidationError;
 
 abstract class ElementValidator {
 
-    static ElementValidator getInstance(EDISimpleType.Base type) {
-        ElementValidator instance;
+    static class ValidatorInstances {
+        static final Map<EDISimpleType.Base, ElementValidator> instances = new EnumMap<>(EDISimpleType.Base.class);
 
-        switch (type) {
-        case IDENTIFIER:
-        case STRING:
-            instance = AlphaNumericValidator.getInstance();
-            break;
-        case NUMERIC:
-            instance = NumericValidator.getInstance();
-            break;
-        case DECIMAL:
-            instance = DecimalValidator.getInstance();
-            break;
-        case DATE:
-            instance = DateValidator.getInstance();
-            break;
-        case TIME:
-            instance = TimeValidator.getInstance();
-            break;
-        case BINARY:
-        default:
-            instance = null;
-            break;
+        static {
+            instances.put(EDISimpleType.Base.IDENTIFIER, new AlphaNumericValidator());
+            instances.put(EDISimpleType.Base.STRING, new AlphaNumericValidator());
+            instances.put(EDISimpleType.Base.NUMERIC, new NumericValidator());
+            instances.put(EDISimpleType.Base.DECIMAL, new DecimalValidator());
+            instances.put(EDISimpleType.Base.DATE, new DateValidator());
+            instances.put(EDISimpleType.Base.TIME, new TimeValidator());
         }
 
-        return instance;
+        private ValidatorInstances() {
+        }
+    }
+
+    static ElementValidator getInstance(EDISimpleType.Base type) {
+        return ValidatorInstances.instances.get(type);
     }
 
     protected static boolean validateLength(Dialect dialect,
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/ExclusionSyntaxValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/ExclusionSyntaxValidator.java
index a117b47..88e68cf 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/ExclusionSyntaxValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/ExclusionSyntaxValidator.java
@@ -20,11 +20,6 @@ import io.xlate.edi.schema.EDISyntaxRule;
 
 class ExclusionSyntaxValidator implements SyntaxValidator {
 
-    static final ExclusionSyntaxValidator INSTANCE = new ExclusionSyntaxValidator();
-
-    private ExclusionSyntaxValidator() {
-    }
-
     @Override
     public void validate(EDISyntaxRule syntax, UsageNode structure, ValidationEventHandler handler, SyntaxStatus status) {
         if (status.elementCount > 1) {
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/FirstOnlySyntaxValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/FirstOnlySyntaxValidator.java
index 5d2e7f9..05bc320 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/FirstOnlySyntaxValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/FirstOnlySyntaxValidator.java
@@ -20,11 +20,6 @@ import io.xlate.edi.schema.EDISyntaxRule;
 
 class FirstOnlySyntaxValidator implements SyntaxValidator {
 
-    static final FirstOnlySyntaxValidator INSTANCE = new FirstOnlySyntaxValidator();
-
-    private FirstOnlySyntaxValidator() {
-    }
-
     @Override
     public void validate(EDISyntaxRule syntax, UsageNode structure, ValidationEventHandler handler, SyntaxStatus status) {
         if (status.anchorPresent && status.elementCount > 1) {
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/ListSyntaxValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/ListSyntaxValidator.java
index 5d83ab5..997bc87 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/ListSyntaxValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/ListSyntaxValidator.java
@@ -20,11 +20,6 @@ import io.xlate.edi.schema.EDISyntaxRule;
 
 class ListSyntaxValidator implements SyntaxValidator {
 
-    static final ListSyntaxValidator INSTANCE = new ListSyntaxValidator();
-
-    private ListSyntaxValidator() {
-    }
-
     @Override
     public void validate(EDISyntaxRule syntax, UsageNode structure, ValidationEventHandler handler, SyntaxStatus status) {
         if (status.anchorPresent && status.elementCount == 1) {
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/NumericValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/NumericValidator.java
index a9eb318..b6d70ac 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/NumericValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/NumericValidator.java
@@ -23,15 +23,6 @@ import io.xlate.edi.stream.EDIStreamValidationError;
 
 class NumericValidator extends ElementValidator {
 
-    private static final NumericValidator singleton = new NumericValidator();
-
-    protected NumericValidator() {
-    }
-
-    static NumericValidator getInstance() {
-        return singleton;
-    }
-
     @Override
     void validate(Dialect dialect, EDISimpleType element, CharSequence value, List<EDIStreamValidationError> errors) {
         int length = validate(dialect, value);
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/PairedSyntaxValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/PairedSyntaxValidator.java
index c5f99f5..1db2258 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/PairedSyntaxValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/PairedSyntaxValidator.java
@@ -20,11 +20,6 @@ import io.xlate.edi.schema.EDISyntaxRule;
 
 class PairedSyntaxValidator implements SyntaxValidator {
 
-    static final PairedSyntaxValidator INSTANCE = new PairedSyntaxValidator();
-
-    private PairedSyntaxValidator() {
-    }
-
     @Override
     public void validate(EDISyntaxRule syntax, UsageNode structure, ValidationEventHandler handler, SyntaxStatus status) {
         if (status.elementCount == 0) {
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/RequiredSyntaxValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/RequiredSyntaxValidator.java
index 84ecdd3..fcfb8b1 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/RequiredSyntaxValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/RequiredSyntaxValidator.java
@@ -20,11 +20,6 @@ import io.xlate.edi.schema.EDISyntaxRule;
 
 class RequiredSyntaxValidator implements SyntaxValidator {
 
-    static final RequiredSyntaxValidator INSTANCE = new RequiredSyntaxValidator();
-
-    private RequiredSyntaxValidator() {
-    }
-
     @Override
     public void validate(EDISyntaxRule syntax, UsageNode structure, ValidationEventHandler handler, SyntaxStatus status) {
         if (status.elementCount < 1) {
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/SingleSyntaxValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/SingleSyntaxValidator.java
index 2044427..33b08e4 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/SingleSyntaxValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/SingleSyntaxValidator.java
@@ -20,11 +20,6 @@ import io.xlate.edi.schema.EDISyntaxRule;
 
 class SingleSyntaxValidator implements SyntaxValidator {
 
-    static final SingleSyntaxValidator INSTANCE = new SingleSyntaxValidator();
-
-    private SingleSyntaxValidator() {
-    }
-
     @Override
     public void validate(EDISyntaxRule syntax, UsageNode structure, ValidationEventHandler handler, SyntaxStatus status) {
         if (status.elementCount > 1) {
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/SyntaxValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/SyntaxValidator.java
index 53a6367..9a07e57 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/SyntaxValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/SyntaxValidator.java
@@ -21,7 +21,9 @@ import static io.xlate.edi.stream.EDIStreamValidationError.CONDITIONAL_REQUIRED_
 import static io.xlate.edi.stream.EDIStreamValidationError.EXCLUSION_CONDITION_VIOLATED;
 import static io.xlate.edi.stream.EDIStreamValidationError.SEGMENT_EXCLUSION_CONDITION_VIOLATED;
 
+import java.util.EnumMap;
 import java.util.List;
+import java.util.Map;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import io.xlate.edi.internal.stream.tokenization.ValidationEventHandler;
@@ -33,34 +35,25 @@ import io.xlate.edi.stream.EDIStreamValidationError;
 
 interface SyntaxValidator {
 
-    static SyntaxValidator getInstance(EDISyntaxRule.Type type) {
-        SyntaxValidator instance = null;
-
-        switch (type) {
-        case CONDITIONAL:
-            instance = ConditionSyntaxValidator.INSTANCE;
-            break;
-        case EXCLUSION:
-            instance = ExclusionSyntaxValidator.INSTANCE;
-            break;
-        case LIST:
-            instance = ListSyntaxValidator.INSTANCE;
-            break;
-        case PAIRED:
-            instance = PairedSyntaxValidator.INSTANCE;
-            break;
-        case REQUIRED:
-            instance = RequiredSyntaxValidator.INSTANCE;
-            break;
-        case SINGLE:
-            instance = SingleSyntaxValidator.INSTANCE;
-            break;
-        case FIRSTONLY:
-            instance = FirstOnlySyntaxValidator.INSTANCE;
-            break;
+    static class ValidatorInstances {
+        static final Map<EDISyntaxRule.Type, SyntaxValidator> instances = new EnumMap<>(EDISyntaxRule.Type.class);
+
+        static {
+            instances.put(EDISyntaxRule.Type.CONDITIONAL, new ConditionSyntaxValidator());
+            instances.put(EDISyntaxRule.Type.EXCLUSION, new ExclusionSyntaxValidator());
+            instances.put(EDISyntaxRule.Type.FIRSTONLY, new FirstOnlySyntaxValidator());
+            instances.put(EDISyntaxRule.Type.LIST, new ListSyntaxValidator());
+            instances.put(EDISyntaxRule.Type.PAIRED, new PairedSyntaxValidator());
+            instances.put(EDISyntaxRule.Type.REQUIRED, new RequiredSyntaxValidator());
+            instances.put(EDISyntaxRule.Type.SINGLE, new SingleSyntaxValidator());
         }
 
-        return instance;
+        private ValidatorInstances() {
+        }
+    }
+
+    static SyntaxValidator getInstance(EDISyntaxRule.Type type) {
+        return ValidatorInstances.instances.get(type);
     }
 
     static class SyntaxStatus {
diff --git a/src/main/java/io/xlate/edi/internal/stream/validation/TimeValidator.java b/src/main/java/io/xlate/edi/internal/stream/validation/TimeValidator.java
index 2876113..43a0551 100644
--- a/src/main/java/io/xlate/edi/internal/stream/validation/TimeValidator.java
+++ b/src/main/java/io/xlate/edi/internal/stream/validation/TimeValidator.java
@@ -23,15 +23,6 @@ import io.xlate.edi.stream.EDIStreamValidationError;
 
 class TimeValidator extends ElementValidator {
 
-    private static final TimeValidator singleton = new TimeValidator();
-
-    private TimeValidator() {
-    }
-
-    static TimeValidator getInstance() {
-        return singleton;
-    }
-
     @Override
     void validate(Dialect dialect,
                   EDISimpleType element,


Test patch:
diff --git a/src/test/java/io/xlate/edi/internal/stream/validation/AlphaNumericValidatorTest.java b/src/test/java/io/xlate/edi/internal/stream/validation/AlphaNumericValidatorTest.java
index aecff41..097f8cd 100644
--- a/src/test/java/io/xlate/edi/internal/stream/validation/AlphaNumericValidatorTest.java
+++ b/src/test/java/io/xlate/edi/internal/stream/validation/AlphaNumericValidatorTest.java
@@ -21,10 +21,12 @@ import io.xlate.edi.stream.EDIStreamValidationError;
 class AlphaNumericValidatorTest implements ValueSetTester {
 
     Dialect dialect;
+    AlphaNumericValidator v;
 
     @BeforeEach
     void setUp() throws EDIException {
         dialect = DialectFactory.getDialect("UNA");
+        v = new AlphaNumericValidator();
         CharacterSet chars = new CharacterSet();
         "UNA=*.?^~UNB*UNOA=3*005435656=1*006415160=1*060515=1434*00000000000778~".chars().forEach(c -> dialect.appendHeader(chars, (char) c));
     }
@@ -39,7 +41,6 @@ class AlphaNumericValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(5L);
         when(element.getMaxLength()).thenReturn(5L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = AlphaNumericValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "TEST", errors);
         assertEquals(1, errors.size());
@@ -56,7 +57,6 @@ class AlphaNumericValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(5L);
         when(element.getMaxLength()).thenReturn(5L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = AlphaNumericValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "TESTTEST", errors);
         assertEquals(1, errors.size());
@@ -74,7 +74,6 @@ class AlphaNumericValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(5L);
         when(element.getValues()).thenReturn(mapOf("VAL1", "Title1", "VAL2", "Title2"));
-        ElementValidator v = AlphaNumericValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "TEST", errors);
         assertEquals(1, errors.size());
@@ -91,7 +90,6 @@ class AlphaNumericValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(5L);
         when(element.getValueSet()).thenReturn(setOf("VAL1", "VAL\u0008"));
-        ElementValidator v = AlphaNumericValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "VAL\u0008", errors);
         assertEquals(1, errors.size());
@@ -107,7 +105,6 @@ class AlphaNumericValidatorTest implements ValueSetTester {
 
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(5L);
-        ElementValidator v = AlphaNumericValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "TESTTEST", output);
         assertHasError(v, dialect, element, output, EDIStreamValidationError.DATA_ELEMENT_TOO_LONG);
@@ -124,7 +121,6 @@ class AlphaNumericValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValues()).thenReturn(mapOf("VAL1", "Title1", "VAL2", "Title2"));
-        ElementValidator v = AlphaNumericValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "TESTTEST", output);
         assertHasError(v, dialect, element, output, EDIStreamValidationError.INVALID_CODE_VALUE);
@@ -140,7 +136,6 @@ class AlphaNumericValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf("VAL1", "VAL2"));
-        ElementValidator v = AlphaNumericValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "VAL1", output);
         assertEquals("VAL1", output.toString());
@@ -155,7 +150,6 @@ class AlphaNumericValidatorTest implements ValueSetTester {
 
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(4L);
-        ElementValidator v = AlphaNumericValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "TES\u0008", output);
         assertHasError(v, dialect, element, output, EDIStreamValidationError.INVALID_CHARACTER_DATA);
@@ -170,7 +164,6 @@ class AlphaNumericValidatorTest implements ValueSetTester {
 
         when(element.getMinLength()).thenReturn(10L);
         when(element.getMaxLength()).thenReturn(10L);
-        ElementValidator v = AlphaNumericValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "TEST", output);
         assertEquals("TEST      ", output.toString());
diff --git a/src/test/java/io/xlate/edi/internal/stream/validation/DateValidatorTest.java b/src/test/java/io/xlate/edi/internal/stream/validation/DateValidatorTest.java
index c418d57..3f4a38c 100644
--- a/src/test/java/io/xlate/edi/internal/stream/validation/DateValidatorTest.java
+++ b/src/test/java/io/xlate/edi/internal/stream/validation/DateValidatorTest.java
@@ -24,10 +24,12 @@ import io.xlate.edi.stream.EDIStreamValidationError;
 class DateValidatorTest implements ValueSetTester {
 
     Dialect dialect;
+    DateValidator v;
 
     @BeforeEach
     void setUp() throws EDIException {
         dialect = DialectFactory.getDialect("UNA");
+        v = new DateValidator();
         CharacterSet chars = new CharacterSet();
         "UNA=*.?^~UNB*UNOA=3*005435656=1*006415160=1*060515=1434*00000000000778~".chars()
                                                                                  .forEach(c -> dialect.appendHeader(chars, (char) c));
@@ -43,7 +45,6 @@ class DateValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = DateValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "0901", errors);
         assertEquals(2, errors.size());
@@ -65,7 +66,6 @@ class DateValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = DateValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, param, errors);
         assertEquals(1, errors.size());
@@ -82,7 +82,6 @@ class DateValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = DateValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "20190901", errors);
         assertEquals(0, errors.size());
@@ -98,7 +97,6 @@ class DateValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = DateValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "191201", errors);
         assertEquals(0, errors.size());
@@ -114,7 +112,6 @@ class DateValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = DateValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "991231", errors);
         v.validate(dialect, element, "990228", errors);
@@ -131,7 +128,6 @@ class DateValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = DateValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "00000132", errors);
         v.validate(dialect, element, "00000431", errors);
@@ -151,7 +147,6 @@ class DateValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = DateValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "20000229", errors);
         v.validate(dialect, element, "19960229", errors);
@@ -170,7 +165,6 @@ class DateValidatorTest implements ValueSetTester {
 
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
-        ElementValidator v = DateValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "20000", output);
         assertHasError(v, dialect, element, output, EDIStreamValidationError.DATA_ELEMENT_TOO_SHORT);
@@ -185,7 +179,6 @@ class DateValidatorTest implements ValueSetTester {
 
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
-        ElementValidator v = DateValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "200001011", output);
         assertHasError(v, dialect, element, output, EDIStreamValidationError.DATA_ELEMENT_TOO_LONG);
@@ -200,7 +193,6 @@ class DateValidatorTest implements ValueSetTester {
 
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
-        ElementValidator v = DateValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "20000100", output);
         assertHasError(v, dialect, element, output, EDIStreamValidationError.INVALID_DATE);
@@ -215,7 +207,6 @@ class DateValidatorTest implements ValueSetTester {
 
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
-        ElementValidator v = DateValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "20000101", output);
         assertEquals("20000101", output.toString());
diff --git a/src/test/java/io/xlate/edi/internal/stream/validation/DecimalValidatorTest.java b/src/test/java/io/xlate/edi/internal/stream/validation/DecimalValidatorTest.java
index 261ad26..93bd099 100644
--- a/src/test/java/io/xlate/edi/internal/stream/validation/DecimalValidatorTest.java
+++ b/src/test/java/io/xlate/edi/internal/stream/validation/DecimalValidatorTest.java
@@ -29,29 +29,29 @@ class DecimalValidatorTest {
 
     @Test
     void testValidateInvalidNegative() {
-        assertEquals(-2, DecimalValidator.getInstance().validate(dialectEdifact, "20-"));
+        assertEquals(-2, new DecimalValidator().validate(dialectEdifact, "20-"));
     }
 
     @Test
     void testValidateValidNegative() {
-        assertEquals(10, DecimalValidator.getInstance().validate(dialectEdifact, "-1234567890"));
+        assertEquals(10, new DecimalValidator().validate(dialectEdifact, "-1234567890"));
     }
 
     @Test
     void testValidateValidDecimal() {
-        assertEquals(4, DecimalValidator.getInstance().validate(dialectEdifact, "20,00"));
-        assertEquals(4, DecimalValidator.getInstance().validate(dialectX12, "20.00"));
+        assertEquals(4, new DecimalValidator().validate(dialectEdifact, "20,00"));
+        assertEquals(4, new DecimalValidator().validate(dialectX12, "20.00"));
     }
 
     @Test
     void testValidateInvalidTooManyDecimalPoints() {
-        assertEquals(-4, DecimalValidator.getInstance().validate(dialectEdifact, "20,00,"));
-        assertEquals(-4, DecimalValidator.getInstance().validate(dialectX12, "20.00."));
+        assertEquals(-4, new DecimalValidator().validate(dialectEdifact, "20,00,"));
+        assertEquals(-4, new DecimalValidator().validate(dialectX12, "20.00."));
     }
 
     @Test
     void testValidateExponentialsValid() {
-        DecimalValidator v = DecimalValidator.getInstance();
+        DecimalValidator v = new DecimalValidator();
         assertEquals(6, v.validate(dialectEdifact, "1,234E-56"));
         assertEquals(6, v.validate(dialectEdifact, "-1,234E-56"));
         assertEquals(2, v.validate(dialectEdifact, "1E2"));
@@ -63,7 +63,7 @@ class DecimalValidatorTest {
 
     @Test
     void testValidateExponentialsInvalid() {
-        DecimalValidator v = DecimalValidator.getInstance();
+        DecimalValidator v = new DecimalValidator();
         assertEquals(-6, v.validate(dialectEdifact, "1,234E-5,6"));
         assertEquals(-6, v.validate(dialectEdifact, "-1,234E-5E-6"));
         assertEquals(-2, v.validate(dialectEdifact, "1E--2,"));
@@ -77,7 +77,7 @@ class DecimalValidatorTest {
 
     @Test
     void testValidateBadExponentialCharacter() {
-        DecimalValidator v = DecimalValidator.getInstance();
+        DecimalValidator v = new DecimalValidator();
         assertEquals(-7, v.validate(dialectEdifact, "1,234e56"));
         assertEquals(-7, v.validate(dialectX12, "1.234e56"));
     }
diff --git a/src/test/java/io/xlate/edi/internal/stream/validation/NumericValidatorTest.java b/src/test/java/io/xlate/edi/internal/stream/validation/NumericValidatorTest.java
index ca9a14f..00af488 100644
--- a/src/test/java/io/xlate/edi/internal/stream/validation/NumericValidatorTest.java
+++ b/src/test/java/io/xlate/edi/internal/stream/validation/NumericValidatorTest.java
@@ -31,12 +31,12 @@ class NumericValidatorTest implements ValueSetTester {
 
     @Test
     void testValidateInvalidNegative() {
-        assertEquals(-2, NumericValidator.getInstance().validate(dialect, "20-"));
+        assertEquals(-2, new NumericValidator().validate(dialect, "20-"));
     }
 
     @Test
     void testValidateValidNegative() {
-        assertEquals(2, NumericValidator.getInstance().validate(dialect, "-20"));
+        assertEquals(2, new NumericValidator().validate(dialect, "-20"));
     }
 
     @Test
@@ -50,7 +50,7 @@ class NumericValidatorTest implements ValueSetTester {
         when(element.getMaxLength()).thenReturn(10L);
         when(element.getValueSet()).thenReturn(setOf());
 
-        ElementValidator v = NumericValidator.getInstance();
+        ElementValidator v = new NumericValidator();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "1234", errors);
         assertEquals(1, errors.size());
@@ -68,7 +68,7 @@ class NumericValidatorTest implements ValueSetTester {
         when(element.getMaxLength()).thenReturn(10L);
         when(element.getValueSet()).thenReturn(setOf());
 
-        ElementValidator v = NumericValidator.getInstance();
+        ElementValidator v = new NumericValidator();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "12345678901", errors);
         assertEquals(1, errors.size());
@@ -86,7 +86,7 @@ class NumericValidatorTest implements ValueSetTester {
         when(element.getMaxLength()).thenReturn(10L);
         when(element.getValueSet()).thenReturn(setOf());
 
-        ElementValidator v = NumericValidator.getInstance();
+        ElementValidator v = new NumericValidator();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "1234F", errors);
         assertEquals(1, errors.size());
@@ -103,7 +103,7 @@ class NumericValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(5L);
 
-        ElementValidator v = NumericValidator.getInstance();
+        ElementValidator v = new NumericValidator();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "123456", output);
         assertHasError(v, dialect, element, output, EDIStreamValidationError.DATA_ELEMENT_TOO_LONG);
@@ -118,7 +118,7 @@ class NumericValidatorTest implements ValueSetTester {
 
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(5L);
-        ElementValidator v = NumericValidator.getInstance();
+        ElementValidator v = new NumericValidator();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "1234F", output);
         assertHasError(v, dialect, element, output, EDIStreamValidationError.INVALID_CHARACTER_DATA);
@@ -135,7 +135,7 @@ class NumericValidatorTest implements ValueSetTester {
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
 
-        ElementValidator v = NumericValidator.getInstance();
+        ElementValidator v = new NumericValidator();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "1234", output);
         assertEquals("1234", output.toString());
@@ -152,7 +152,7 @@ class NumericValidatorTest implements ValueSetTester {
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
 
-        ElementValidator v = NumericValidator.getInstance();
+        ElementValidator v = new NumericValidator();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "123", output);
         assertEquals("000123", output.toString());
diff --git a/src/test/java/io/xlate/edi/internal/stream/validation/TimeValidatorTest.java b/src/test/java/io/xlate/edi/internal/stream/validation/TimeValidatorTest.java
index cdb2f14..4356d88 100644
--- a/src/test/java/io/xlate/edi/internal/stream/validation/TimeValidatorTest.java
+++ b/src/test/java/io/xlate/edi/internal/stream/validation/TimeValidatorTest.java
@@ -23,10 +23,12 @@ import io.xlate.edi.stream.EDIStreamValidationError;
 class TimeValidatorTest implements ValueSetTester {
 
     Dialect dialect;
+    TimeValidator v;
 
     @BeforeEach
     void setUp() throws EDIException {
         dialect = DialectFactory.getDialect("UNA");
+        v = new TimeValidator();
         CharacterSet chars = new CharacterSet();
         "UNA=*.?^~UNB*UNOA=3*005435656=1*006415160=1*060515=1434*00000000000778~".chars().forEach(c -> dialect.appendHeader(chars, (char) c));
     }
@@ -41,7 +43,6 @@ class TimeValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = TimeValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "09", errors);
         assertEquals(2, errors.size());
@@ -59,7 +60,6 @@ class TimeValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = TimeValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "1230599999", errors);
         assertEquals(2, errors.size());
@@ -77,7 +77,6 @@ class TimeValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = TimeValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "123059AA", errors);
         assertEquals(1, errors.size());
@@ -95,7 +94,6 @@ class TimeValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = TimeValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "12305", errors);
         assertEquals(1, errors.size());
@@ -112,7 +110,6 @@ class TimeValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = TimeValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "12305900", errors);
         assertEquals(0, errors.size());
@@ -128,7 +125,6 @@ class TimeValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = TimeValidator.getInstance();
         List<EDIStreamValidationError> errors = new ArrayList<>();
         v.validate(dialect, element, "1230591", errors);
         assertEquals(0, errors.size());
@@ -158,7 +154,6 @@ class TimeValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = TimeValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "1230599999", output);
         assertHasError(v, dialect, element, output, EDIStreamValidationError.DATA_ELEMENT_TOO_LONG);
@@ -174,7 +169,6 @@ class TimeValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = TimeValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "123059AA", output);
         assertHasError(v, dialect, element, output, EDIStreamValidationError.INVALID_TIME);
@@ -190,7 +184,6 @@ class TimeValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(4L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = TimeValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "123059", output);
         assertEquals("123059", output.toString());
@@ -206,7 +199,6 @@ class TimeValidatorTest implements ValueSetTester {
         when(element.getMinLength()).thenReturn(6L);
         when(element.getMaxLength()).thenReturn(8L);
         when(element.getValueSet()).thenReturn(setOf());
-        ElementValidator v = TimeValidator.getInstance();
         StringBuilder output = new StringBuilder();
         v.format(dialect, element, "1230", output);
         assertEquals("123000", output.toString());