From 5a482680012576018f684c493311be8d1fb43510 Mon Sep 17 00:00:00 2001
From: felmer <felmer>
Date: Tue, 24 Nov 2009 13:45:59 +0000
Subject: [PATCH] LMS-1277 implemented and tested

SVN: 13493
---
 .../validation/AbstractValidator.java         |  8 ++++--
 .../validation/AbstractValidatorFactory.java  | 26 +++++++++++++++---
 .../validation/ColumnDefinition.java          |  2 +-
 .../validation/NumericValidatorFactory.java   |  7 ++---
 .../validation/RegExBasedValidator.java       | 12 +++++++--
 .../validation/StringValidatorFactory.java    |  2 +-
 .../validation/UniqueValidatorFactory.java    |  2 +-
 .../NumericValidatorFactoryTest.java          | 20 ++++++++++++++
 .../StringValidatorFactoryTest.java           | 27 +++++++++++++++++++
 9 files changed, 92 insertions(+), 14 deletions(-)

diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AbstractValidator.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AbstractValidator.java
index 867417a5563..1c87958daaf 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AbstractValidator.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AbstractValidator.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.etlserver.validation;
 
+import java.util.Set;
+
 import org.apache.commons.lang.StringUtils;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
@@ -28,17 +30,19 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException;
 abstract class AbstractValidator implements IValidator
 {
     private final boolean allowEmptyValues;
+    private final Set<String> emptyValueSynonyms;
     
-    AbstractValidator(boolean allowEmptyValues)
+    AbstractValidator(boolean allowEmptyValues, Set<String> emptyValueSynonyms)
     {
         this.allowEmptyValues = allowEmptyValues;
+        this.emptyValueSynonyms = emptyValueSynonyms;
     }
     
     public final void assertValid(String value)
     {
         if (allowEmptyValues)
         {
-            if (StringUtils.isBlank(value))
+            if (StringUtils.isBlank(value) || emptyValueSynonyms.contains(value.trim()))
             {
                 return;
             }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AbstractValidatorFactory.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AbstractValidatorFactory.java
index 3195ff3c9f7..6a6cd98b407 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AbstractValidatorFactory.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AbstractValidatorFactory.java
@@ -16,24 +16,42 @@
 
 package ch.systemsx.cisd.etlserver.validation;
 
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashSet;
 import java.util.Properties;
+import java.util.Set;
 
 import ch.systemsx.cisd.common.utilities.PropertyUtils;
+import ch.systemsx.cisd.openbis.dss.generic.shared.utils.PropertyParametersUtil;
 
 /**
- * 
- *
  * @author Franz-Josef Elmer
  */
 abstract class AbstractValidatorFactory implements IValidatorFactory
 {
     static final String ALLOW_EMPTY_VALUES_KEY = "allow-empty-values";
-    
+
+    static final String EMPTY_VALUE_SYNONYMS_KEY = "empty-value-synonyms";
+
     protected final boolean allowEmptyValues;
-    
+
+    protected final Set<String> emptyValueSynonyms;
+
     AbstractValidatorFactory(Properties properties)
     {
         allowEmptyValues = PropertyUtils.getBoolean(properties, ALLOW_EMPTY_VALUES_KEY, false);
+        String property = properties.getProperty(EMPTY_VALUE_SYNONYMS_KEY);
+        if (property == null)
+        {
+            emptyValueSynonyms = Collections.emptySet();
+        } else
+        {
+            String[] synonyms =
+                    PropertyParametersUtil
+                            .parseItemisedProperty(property, EMPTY_VALUE_SYNONYMS_KEY);
+            emptyValueSynonyms = new LinkedHashSet<String>(Arrays.asList(synonyms));
+        }
     }
 
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/ColumnDefinition.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/ColumnDefinition.java
index 111e88c106b..a8d5f53a426 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/ColumnDefinition.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/ColumnDefinition.java
@@ -67,7 +67,7 @@ class ColumnDefinition
         if (headerValidatorName == null)
         {
             String headerPattern = properties.getProperty(HEADER_PATTERN_KEY, ".*");
-            headerValidator = new RegExBasedValidator(false, headerPattern);
+            headerValidator = new RegExBasedValidator(headerPattern);
         } else
         {
             headerValidator =
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/NumericValidatorFactory.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/NumericValidatorFactory.java
index f7209e601f1..36918e2c258 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/NumericValidatorFactory.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/NumericValidatorFactory.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.etlserver.validation;
 
 import java.util.Properties;
+import java.util.Set;
 
 import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
@@ -117,9 +118,9 @@ class NumericValidatorFactory extends AbstractValidatorFactory
     {
         private final Range rangeOrNull;
         
-        NumericValidator(boolean allowEmptyValues, Range rangeOrNull)
+        NumericValidator(boolean allowEmptyValues, Set<String> emptyValueSynonyms, Range rangeOrNull)
         {
-            super(allowEmptyValues);
+            super(allowEmptyValues, emptyValueSynonyms);
             this.rangeOrNull = rangeOrNull;
         }
         
@@ -148,7 +149,7 @@ class NumericValidatorFactory extends AbstractValidatorFactory
         super(properties);
         String valueRange = properties.getProperty(VALUE_RANGE_KEY);
         Range rangeOrNull = valueRange == null ? null : new Range(valueRange);
-        validator = new NumericValidator(allowEmptyValues, rangeOrNull);
+        validator = new NumericValidator(allowEmptyValues, emptyValueSynonyms, rangeOrNull);
     }
 
     public IValidator createValidator()
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/RegExBasedValidator.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/RegExBasedValidator.java
index d17c224d737..75309d99559 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/RegExBasedValidator.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/RegExBasedValidator.java
@@ -16,6 +16,8 @@
 
 package ch.systemsx.cisd.etlserver.validation;
 
+import java.util.Collections;
+import java.util.Set;
 import java.util.regex.Pattern;
 
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
@@ -28,10 +30,16 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException;
 class RegExBasedValidator extends AbstractValidator implements IColumnHeaderValidator
 {
     private final Pattern pattern;
+    
+    RegExBasedValidator(String regularExpression)
+    {
+        this(false, Collections.<String>emptySet(), regularExpression);
+    }
 
-    RegExBasedValidator(boolean allowEmptyValues, String regularExpression)
+    RegExBasedValidator(boolean allowEmptyValues, Set<String> emptyValueSynonyms,
+            String regularExpression)
     {
-        super(allowEmptyValues);
+        super(allowEmptyValues, emptyValueSynonyms);
         pattern = Pattern.compile(regularExpression);
     }
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/StringValidatorFactory.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/StringValidatorFactory.java
index 3241e22e92c..fd7fe9a691f 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/StringValidatorFactory.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/StringValidatorFactory.java
@@ -35,7 +35,7 @@ class StringValidatorFactory extends AbstractValidatorFactory
     {
         super(properties);
         String regex = PropertyUtils.getMandatoryProperty(properties, VALUE_PATTERN_KEY);
-        validator = new RegExBasedValidator(allowEmptyValues, regex);
+        validator = new RegExBasedValidator(allowEmptyValues, emptyValueSynonyms, regex);
     }
     
     public IValidator createValidator()
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/UniqueValidatorFactory.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/UniqueValidatorFactory.java
index 2685e2c86b6..8022f812693 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/UniqueValidatorFactory.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/UniqueValidatorFactory.java
@@ -39,7 +39,7 @@ class UniqueValidatorFactory implements IValidatorFactory
             validator = AnyValidatorFactory.INSTANCE.createValidator();
         } else
         {
-            validator = new RegExBasedValidator(false, regex);
+            validator = new RegExBasedValidator(regex);
         }
     }
 
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/NumericValidatorFactoryTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/NumericValidatorFactoryTest.java
index bb7e8831aa2..4aa172471c8 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/NumericValidatorFactoryTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/NumericValidatorFactoryTest.java
@@ -161,6 +161,26 @@ public class NumericValidatorFactoryTest extends AssertJUnit
         assertFailingToSmall("<= 0.0", validator, "0.0");
     }
     
+    @Test
+    public void testAllowEmptyValueSynonyms()
+    {
+        Properties properties = new Properties();
+        properties.setProperty(NumericValidatorFactory.ALLOW_EMPTY_VALUES_KEY, "true");
+        properties.setProperty(NumericValidatorFactory.EMPTY_VALUE_SYNONYMS_KEY, "-, N/A");
+        properties.setProperty(NumericValidatorFactory.VALUE_RANGE_KEY, "(0,1]");
+        NumericValidatorFactory validatorFactory = new NumericValidatorFactory(properties);
+        IValidator validator = validatorFactory.createValidator();
+        
+        validator.assertValid(null);
+        validator.assertValid("");
+        validator.assertValid("  ");
+        validator.assertValid("-");
+        validator.assertValid("N/A");
+        assertNotANumber(validator, "n/a");
+        assertFailingToLarge("> 1.0", validator, "1.25");
+        assertFailingToSmall("<= 0.0", validator, "0.0");
+    }
+    
     @Test
     public void testNoRange()
     {
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/StringValidatorFactoryTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/StringValidatorFactoryTest.java
index 5f1c06b796b..683020958b0 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/StringValidatorFactoryTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/StringValidatorFactoryTest.java
@@ -98,4 +98,31 @@ public class StringValidatorFactoryTest extends AssertJUnit
             assertEquals("'bc' doesn't match the following regular expression: a.*", ex.getMessage());
         }
     }
+    
+    @Test
+    public void testEmptyValueSynonyms()
+    {
+        Properties properties = new Properties();
+        properties.setProperty(StringValidatorFactory.VALUE_PATTERN_KEY, "a.*");
+        properties.setProperty(StringValidatorFactory.ALLOW_EMPTY_VALUES_KEY, "yes");
+        properties.setProperty(StringValidatorFactory.EMPTY_VALUE_SYNONYMS_KEY, "-");
+        StringValidatorFactory factory = new StringValidatorFactory(properties);
+        IValidator validator = factory.createValidator();
+        
+        validator.assertValid("a");
+        validator.assertValid("a1");
+        validator.assertValid("abc");
+        validator.assertValid(null);
+        validator.assertValid("");
+        validator.assertValid("  ");
+        validator.assertValid("-");
+        try
+        {
+            validator.assertValid("N/A");
+            fail("UserFailureException expected");
+        } catch (UserFailureException ex)
+        {
+            assertEquals("'N/A' doesn't match the following regular expression: a.*", ex.getMessage());
+        }
+    }
 }
-- 
GitLab