From 4e38d93f49d91ca9a5fa420ed82d597106735b0d Mon Sep 17 00:00:00 2001 From: felmer <felmer> Date: Thu, 17 Dec 2009 11:59:34 +0000 Subject: [PATCH] SE-178 extend validation framework: Value validators can be created depending on column header. Using this possibility in HeaderBasedValueValidatorFactory. Unit tests missing. SVN: 13984 --- .../validation/AnyValidatorFactory.java | 2 +- .../validation/ColumnDefinition.java | 14 ++- .../validation/DataSetValidatorForTSV.java | 2 +- .../DefaultValueValidatorFactory.java | 4 +- .../HeaderBasedValueValidatorFactory.java | 107 ++++++++++++++++++ .../validation/IValidatorFactory.java | 6 +- .../validation/NumericValidatorFactory.java | 2 +- .../validation/StringValidatorFactory.java | 2 +- .../validation/UniqueValidatorFactory.java | 4 +- .../validation/ColumnDefinitionTest.java | 14 +-- .../DataSetValidatorForTSVTest.java | 2 +- .../NumericValidatorFactoryTest.java | 12 +- .../StringValidatorFactoryTest.java | 6 +- .../UniqueValidatorFactoryTest.java | 8 +- 14 files changed, 149 insertions(+), 36 deletions(-) create mode 100644 datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/HeaderBasedValueValidatorFactory.java diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AnyValidatorFactory.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AnyValidatorFactory.java index aac80a707e7..7c68dc191b4 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AnyValidatorFactory.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/AnyValidatorFactory.java @@ -32,7 +32,7 @@ final class AnyValidatorFactory implements IValidatorFactory { } - public IValidator createValidator() + public IValidator createValidator(String header) { return VALIDATOR; } 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 eb8a4ee1ad3..9a31bebde14 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 @@ -77,13 +77,19 @@ class ColumnDefinition ClassUtils.create(IColumnHeaderValidator.class, headerValidatorName, headerValidatorProperties); } + IValidatorFactory factory = createValidatorFactory(properties); + return new ColumnDefinition(name, headerValidator, factory, mandatory, order, + canDefineMultipleColumns); + } + + static IValidatorFactory createValidatorFactory(Properties properties) + { String validatorFactoryName = properties.getProperty(VALUE_VALIDATOR_KEY, DefaultValueValidatorFactory.class .getName()); IValidatorFactory factory = ClassUtils.create(IValidatorFactory.class, validatorFactoryName, properties); - return new ColumnDefinition(name, headerValidator, factory, mandatory, order, - canDefineMultipleColumns); + return factory; } private ColumnDefinition(String name, IColumnHeaderValidator headerValidator, @@ -134,8 +140,8 @@ class ColumnDefinition return headerValidator.validateHeader(header); } - IValidator createValidator() + IValidator createValidator(String header) { - return valueValidatorFactory.createValidator(); + return valueValidatorFactory.createValidator(header); } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/DataSetValidatorForTSV.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/DataSetValidatorForTSV.java index 3b2e2dd9638..952126f31a6 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/DataSetValidatorForTSV.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/DataSetValidatorForTSV.java @@ -160,7 +160,7 @@ class DataSetValidatorForTSV implements IDataSetValidator IValidator[] validators = new IValidator[definitions.length]; for (int i = 0; i < validators.length; i++) { - validators[i] = definitions[i].createValidator(); + validators[i] = definitions[i].createValidator(headers.get(i)); } int lineNumber = 1; while (table.hasMoreRows()) diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/DefaultValueValidatorFactory.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/DefaultValueValidatorFactory.java index c6241da68ec..32dcd929832 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/DefaultValueValidatorFactory.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/DefaultValueValidatorFactory.java @@ -89,9 +89,9 @@ public class DefaultValueValidatorFactory implements IValidatorFactory factory = valueType.createFactory(properties); } - public IValidator createValidator() + public IValidator createValidator(String header) { - return factory.createValidator(); + return factory.createValidator(header); } } diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/HeaderBasedValueValidatorFactory.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/HeaderBasedValueValidatorFactory.java new file mode 100644 index 00000000000..beae32c8ac0 --- /dev/null +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/HeaderBasedValueValidatorFactory.java @@ -0,0 +1,107 @@ +/* + * Copyright 2009 ETH Zuerich, CISD + * + * Licensed 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 ch.systemsx.cisd.etlserver.validation; + +import java.util.ArrayList; +import java.util.List; +import java.util.Properties; +import java.util.regex.Pattern; + +import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException; +import ch.systemsx.cisd.common.utilities.PropertyUtils; +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.PropertyParametersUtil; +import ch.systemsx.cisd.openbis.dss.generic.shared.utils.PropertyParametersUtil.SectionProperties; +import ch.systemsx.cisd.openbis.generic.client.web.client.exception.UserFailureException; + +/** + * + * + * @author Franz-Josef Elmer + */ +public class HeaderBasedValueValidatorFactory implements IValidatorFactory, IColumnHeaderValidator +{ + private static final class HeaderPatternAndFactory + { + private final Pattern pattern; + private final IValidatorFactory factory; + + HeaderPatternAndFactory(Pattern pattern, IValidatorFactory factory) + { + super(); + this.pattern = pattern; + this.factory = factory; + } + } + + private static final String HEADER_PATTERN_KEY = "header-pattern"; + private static final String HEADER_TYPES_KEY = "header-types"; + + private final List<HeaderPatternAndFactory> factories = new ArrayList<HeaderPatternAndFactory>(); + private final String headerMessage; + + public HeaderBasedValueValidatorFactory(Properties properties) + { + SectionProperties[] columnsProperties = + PropertyParametersUtil.extractSectionProperties(properties, HEADER_TYPES_KEY, false); + StringBuilder builder = new StringBuilder(); + for (SectionProperties sectionProperties : columnsProperties) + { + String key = sectionProperties.getKey(); + Properties props = sectionProperties.getProperties(); + String pattern = PropertyUtils.getMandatoryProperty(props, HEADER_PATTERN_KEY); + builder.append('\n').append("Regular expression header of type '").append(key); + builder.append("' have to match: ").append(pattern); + try + { + factories.add(new HeaderPatternAndFactory(Pattern.compile(pattern), + ColumnDefinition.createValidatorFactory(props))); + } catch (Exception ex) + { + throw new ConfigurationFailureException("Invalid header pattern for header type '" + + key + "': " + pattern); + } + } + headerMessage = builder.toString(); + } + + public Result validateHeader(String header) + { + for (HeaderPatternAndFactory factory : factories) + { + if (factory.pattern.matcher(header).matches()) + { + return Result.OK; + } + } + return Result.failure("Does not match: " + headerMessage); + } + + public IValidator createValidator(String columnHeader) + { + for (HeaderPatternAndFactory factory : factories) + { + if (factory.pattern.matcher(columnHeader).matches()) + { + return factory.factory.createValidator(columnHeader); + } + } + throw new UserFailureException("No value validatory found for header '" + columnHeader + + "': " + headerMessage); + } + + +} diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/IValidatorFactory.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/IValidatorFactory.java index 4e42035830d..934d1be149b 100644 --- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/IValidatorFactory.java +++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/validation/IValidatorFactory.java @@ -24,8 +24,8 @@ package ch.systemsx.cisd.etlserver.validation; public interface IValidatorFactory { /** - * Creates a validator. The same instance can be returned as in a previous call if the - * validator object is immutable. + * Creates a validator for the specified column header. The same instance can be returned as in + * a previous call for the same argument if the validator object is immutable and the . */ - public IValidator createValidator(); + public IValidator createValidator(String columnHeader); } 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 36918e2c258..904f1b98a65 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 @@ -152,7 +152,7 @@ class NumericValidatorFactory extends AbstractValidatorFactory validator = new NumericValidator(allowEmptyValues, emptyValueSynonyms, rangeOrNull); } - public IValidator createValidator() + public IValidator createValidator(String header) { return validator; } 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 fd7fe9a691f..0ae8424e943 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 @@ -38,7 +38,7 @@ class StringValidatorFactory extends AbstractValidatorFactory validator = new RegExBasedValidator(allowEmptyValues, emptyValueSynonyms, regex); } - public IValidator createValidator() + public IValidator createValidator(String header) { return validator; } 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 8022f812693..9dc1cb5160e 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 @@ -36,14 +36,14 @@ class UniqueValidatorFactory implements IValidatorFactory String regex = properties.getProperty(StringValidatorFactory.VALUE_PATTERN_KEY); if (regex == null) { - validator = AnyValidatorFactory.INSTANCE.createValidator(); + validator = AnyValidatorFactory.INSTANCE.createValidator(null); } else { validator = new RegExBasedValidator(regex); } } - public IValidator createValidator() + public IValidator createValidator(String header) { return new IValidator() { diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/ColumnDefinitionTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/ColumnDefinitionTest.java index 5ffc3f0c27b..b316c9cf410 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/ColumnDefinitionTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/ColumnDefinitionTest.java @@ -40,7 +40,7 @@ public class ColumnDefinitionTest extends AssertJUnit { ColumnDefinition definition = ColumnDefinition.create("col", new Properties()); - IValidator validator = definition.createValidator(); + IValidator validator = definition.createValidator("blabla"); validator.assertValid(null); validator.assertValid(""); validator.assertValid("abc"); @@ -97,7 +97,7 @@ public class ColumnDefinitionTest extends AssertJUnit props.setProperty(ColumnDefinition.ORDER_KEY, "1"); ColumnDefinition definition = ColumnDefinition.create("col", props); - IValidator validator = definition.createValidator(); + IValidator validator = definition.createValidator("blabla"); validator.assertValid(null); validator.assertValid(""); validator.assertValid("abc"); @@ -120,7 +120,7 @@ public class ColumnDefinitionTest extends AssertJUnit ColumnDefinition definition = ColumnDefinition.create("col", props); // We did not specify anything about the value -- these should all pass - IValidator valueValidator = definition.createValidator(); + IValidator valueValidator = definition.createValidator("blabla"); valueValidator.assertValid(null); valueValidator.assertValid(""); valueValidator.assertValid("abc"); @@ -164,7 +164,7 @@ public class ColumnDefinitionTest extends AssertJUnit ColumnDefinition definition = ColumnDefinition.create("col", props); // We did not specify anything about the value -- these should all pass - IValidator valueValidator = definition.createValidator(); + IValidator valueValidator = definition.createValidator("blabla"); valueValidator.assertValid(null); valueValidator.assertValid(""); valueValidator.assertValid("abc"); @@ -282,7 +282,7 @@ public class ColumnDefinitionTest extends AssertJUnit props.setProperty(DefaultValueValidatorFactory.VALUE_TYPE_KEY, "numeric"); ColumnDefinition definition = ColumnDefinition.create("col", props); - IValidator valueValidator = definition.createValidator(); + IValidator valueValidator = definition.createValidator("blabla"); try { valueValidator.assertValid(null); @@ -340,7 +340,7 @@ public class ColumnDefinitionTest extends AssertJUnit props.setProperty(DefaultValueValidatorFactory.VALUE_TYPE_KEY, "string"); props.setProperty(StringValidatorFactory.VALUE_PATTERN_KEY, "[0-9]+"); definition = ColumnDefinition.create("col", props); - valueValidator = definition.createValidator(); + valueValidator = definition.createValidator("blabla"); try { valueValidator.assertValid(null); @@ -387,7 +387,7 @@ public class ColumnDefinitionTest extends AssertJUnit props.setProperty(StringValidatorFactory.VALUE_PATTERN_KEY, ".+ :.*"); props.setProperty(AbstractValidatorFactory.ALLOW_EMPTY_VALUES_KEY, "true"); definition = ColumnDefinition.create("col", props); - valueValidator = definition.createValidator(); + valueValidator = definition.createValidator("blabla"); try { diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/DataSetValidatorForTSVTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/DataSetValidatorForTSVTest.java index 2484792d8c3..8819157eef0 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/DataSetValidatorForTSVTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/DataSetValidatorForTSVTest.java @@ -93,7 +93,7 @@ public class DataSetValidatorForTSVTest extends AbstractFileSystemTestCase validator = new MockValidator(properties); } - public IValidator createValidator() + public IValidator createValidator(String header) { return validator; } 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 4aa172471c8..5898fb3c593 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 @@ -127,7 +127,7 @@ public class NumericValidatorFactoryTest extends AssertJUnit public void testInvalidNumber() { NumericValidatorFactory validatorFactory = new NumericValidatorFactory(new Properties()); - IValidator validator = validatorFactory.createValidator(); + IValidator validator = validatorFactory.createValidator("blabla"); assertNotANumber(validator, "abc"); assertNotANumber(validator, " -0-"); @@ -137,7 +137,7 @@ public class NumericValidatorFactoryTest extends AssertJUnit public void testEmptyValue() { NumericValidatorFactory validatorFactory = new NumericValidatorFactory(new Properties()); - IValidator validator = validatorFactory.createValidator(); + IValidator validator = validatorFactory.createValidator("blabla"); assertFailingOnBlankValue(validator, null); assertFailingOnBlankValue(validator, ""); @@ -151,7 +151,7 @@ public class NumericValidatorFactoryTest extends AssertJUnit properties.setProperty(NumericValidatorFactory.ALLOW_EMPTY_VALUES_KEY, "true"); properties.setProperty(NumericValidatorFactory.VALUE_RANGE_KEY, "(0,1]"); NumericValidatorFactory validatorFactory = new NumericValidatorFactory(properties); - IValidator validator = validatorFactory.createValidator(); + IValidator validator = validatorFactory.createValidator("blabla"); validator.assertValid(null); validator.assertValid(""); @@ -169,7 +169,7 @@ public class NumericValidatorFactoryTest extends AssertJUnit 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(); + IValidator validator = validatorFactory.createValidator("blabla"); validator.assertValid(null); validator.assertValid(""); @@ -185,7 +185,7 @@ public class NumericValidatorFactoryTest extends AssertJUnit public void testNoRange() { NumericValidatorFactory validatorFactory = new NumericValidatorFactory(new Properties()); - IValidator validator = validatorFactory.createValidator(); + IValidator validator = validatorFactory.createValidator("blabla"); validator.assertValid("-Infinity"); validator.assertValid("-1"); @@ -226,7 +226,7 @@ public class NumericValidatorFactoryTest extends AssertJUnit Properties properties = new Properties(); properties.setProperty(NumericValidatorFactory.VALUE_RANGE_KEY, range); NumericValidatorFactory validatorFactory = new NumericValidatorFactory(properties); - return validatorFactory.createValidator(); + return validatorFactory.createValidator("blabla"); } private void assertFailingOnBlankValue(IValidator validator, String value) 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 eb7fcff95c7..deef95c8184 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 @@ -51,7 +51,7 @@ public class StringValidatorFactoryTest extends AssertJUnit Properties properties = new Properties(); properties.setProperty(StringValidatorFactory.VALUE_PATTERN_KEY, "a.*"); StringValidatorFactory factory = new StringValidatorFactory(properties); - IValidator validator = factory.createValidator(); + IValidator validator = factory.createValidator("blabla"); validator.assertValid("a"); validator.assertValid("a1"); @@ -82,7 +82,7 @@ public class StringValidatorFactoryTest extends AssertJUnit properties.setProperty(StringValidatorFactory.VALUE_PATTERN_KEY, "a.*"); properties.setProperty(StringValidatorFactory.ALLOW_EMPTY_VALUES_KEY, "yes"); StringValidatorFactory factory = new StringValidatorFactory(properties); - IValidator validator = factory.createValidator(); + IValidator validator = factory.createValidator("blabla"); validator.assertValid("a"); validator.assertValid("a1"); @@ -109,7 +109,7 @@ public class StringValidatorFactoryTest extends AssertJUnit properties.setProperty(StringValidatorFactory.ALLOW_EMPTY_VALUES_KEY, "yes"); properties.setProperty(StringValidatorFactory.EMPTY_VALUE_SYNONYMS_KEY, "-"); StringValidatorFactory factory = new StringValidatorFactory(properties); - IValidator validator = factory.createValidator(); + IValidator validator = factory.createValidator("blabla"); validator.assertValid("a"); validator.assertValid("a1"); diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/UniqueValidatorFactoryTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/UniqueValidatorFactoryTest.java index ef24e49bb59..48949fdb626 100644 --- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/UniqueValidatorFactoryTest.java +++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/validation/UniqueValidatorFactoryTest.java @@ -34,7 +34,7 @@ public class UniqueValidatorFactoryTest extends AssertJUnit public void testNoPattern() { UniqueValidatorFactory factory = new UniqueValidatorFactory(new Properties()); - IValidator validator = factory.createValidator(); + IValidator validator = factory.createValidator("blabla"); validator.assertValid("a"); validator.assertValid("b"); @@ -54,7 +54,7 @@ public class UniqueValidatorFactoryTest extends AssertJUnit Properties properties = new Properties(); properties.setProperty(StringValidatorFactory.VALUE_PATTERN_KEY, "a[0-9]*"); UniqueValidatorFactory factory = new UniqueValidatorFactory(properties); - IValidator validator = factory.createValidator(); + IValidator validator = factory.createValidator("blabla"); validator.assertValid("a"); validator.assertValid("a1"); @@ -74,11 +74,11 @@ public class UniqueValidatorFactoryTest extends AssertJUnit public void testCreateValidatorReturnsFreshValidator() { UniqueValidatorFactory factory = new UniqueValidatorFactory(new Properties()); - IValidator validator = factory.createValidator(); + IValidator validator = factory.createValidator("blabla"); validator.assertValid("a"); - validator = factory.createValidator(); + validator = factory.createValidator("blabla"); validator.assertValid("a"); } -- GitLab