/* * chombo: Hadoop Map Reduce utility * Author: Pranab Ghosh * * 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 org.chombo.validator; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.List; import java.util.Map; import org.chombo.util.ProcessorAttribute; import com.typesafe.config.Config; import com.typesafe.config.ConfigException; /** * @author pranab * */ public class ValidatorFactory { public static final String MIN_VALIDATOR = "min"; public static final String MAX_VALIDATOR = "max"; public static final String MIN_LENGTH_VALIDATOR = "minLength"; public static final String MAX_LENGTH_VALIDATOR = "maxLength"; public static final String EXACT_LENGTH_VALIDATOR = "exactLength"; public static final String NOT_MISSING_VALIDATOR = "notMissing"; public static final String PATTERN_VALIDATOR = "pattern"; public static final String MEMEBERSHIP_VALIDATOR = "membership"; public static final String ENSURE_INT_VALIDATOR = "ensureInt"; public static final String ENSURE_LONG_VALIDATOR = "ensureLong"; public static final String ENSURE_DOUBLE_VALIDATOR = "ensureDouble"; public static final String ENSURE_DATE_VALIDATOR = "ensureDate"; public static final String ZCORE_BASED_RANGE_VALIDATOR = "zscoreBasedRange"; public static final String ROBUST_ZCORE_BASED_RANGE_VALIDATOR = "robustZscoreBasedRange"; private static Map<String,String> custValidatorClasses = new HashMap<String,String>(); private static Map<String,Validator> custValidators = new HashMap<String,Validator>(); private static CustomValidatorFactory customValidatorFactory; /** * @param customValidFactoryClass * @param validatorConfig */ public static void initialize(String customValidFactoryClass, Config validatorConfig) { if (null != customValidFactoryClass) { Class<?>factoryCls = null; try { factoryCls = Class.forName(customValidFactoryClass); customValidatorFactory = (CustomValidatorFactory)factoryCls.newInstance(); } catch (ClassNotFoundException cne) { throw new IllegalArgumentException("custom validation factory class could not be created " + cne.getMessage()); } catch (InstantiationException ie) { throw new IllegalStateException("custom validation factory instance could not be created " + ie.getMessage()); } catch (IllegalAccessException iae) { throw new IllegalStateException("custom validation factory instance could not be created with access issue " + iae.getMessage()); } } //custom validaor classes if (null == customValidatorFactory && null != validatorConfig) { if (validatorConfig.hasPath("validators.customValidators")) { List <? extends Config> customValidConfigs = validatorConfig.getConfigList("validators.customValidators"); for (Config customValidConfig : customValidConfigs ) { custValidatorClasses.put("custom.validator.class." + customValidConfig.getString("tag"), customValidConfig.getString("class")); } } } } /** * @param tag * @param ordinal * @param schema * @return */ public static Validator create(String validatorType, ProcessorAttribute prAttr) { return create(validatorType, prAttr, null, null); } /** * @param tag * @param ordinal * @param schema * @return */ public static Validator create(String validatorType, ProcessorAttribute prAttr, Map<String, Object> validatorContext) { return create(validatorType, prAttr, validatorContext, null); } /** * @param tag * @param ordinal * @param schema * @return */ public static Validator create(String validatorType, ProcessorAttribute prAttr, Config validatorConfig) { return create(validatorType, prAttr, null, validatorConfig); } /** * @param validatorType * @param prAttr * @param validatorContext * @param validatorConfig * @return */ public static Validator create(String validatorType, ProcessorAttribute prAttr, Map<String, Object> validatorContext, Config validatorConfig) { Validator validator = null; if (validatorType.equals(MIN_VALIDATOR)) { if (prAttr.isInteger()) { validator = new NumericalValidator.IntMinValidator(validatorType, prAttr); } else if (prAttr.isDouble()) { validator = new NumericalValidator.DoubleMinValidator(validatorType, prAttr); } else if (prAttr.isString()) { validator = new StringValidator.MinValidator(validatorType, prAttr); } } else if (validatorType.equals(MAX_VALIDATOR)) { if (prAttr.isInteger()) { validator = new NumericalValidator.IntMaxValidator(validatorType, prAttr); } else if (prAttr.isDouble()) { validator = new NumericalValidator.DoubleMaxValidator(validatorType, prAttr); } else if (prAttr.isString()) { validator = new StringValidator.MaxValidator(validatorType, prAttr); } } else if (validatorType.equals(MIN_LENGTH_VALIDATOR)) { if (prAttr.isString()) { validator = new StringValidator.MinLengthValidator(validatorType, prAttr); } } else if (validatorType.equals(MAX_LENGTH_VALIDATOR)) { if (prAttr.isString()) { validator = new StringValidator.MaxLengthValidator(validatorType, prAttr); } } else if (validatorType.equals(EXACT_LENGTH_VALIDATOR)) { if (prAttr.isString()) { validator = new StringValidator.LengthValidator(validatorType, prAttr); } } else if (validatorType.equals(NOT_MISSING_VALIDATOR)) { validator = new GenericValidator.NotMissingValidator(validatorType, prAttr); } else if (validatorType.equals(PATTERN_VALIDATOR)) { if (prAttr.isString()) { validator = new StringValidator.PatternValidator(validatorType, prAttr); } } else if (validatorType.equals(MEMEBERSHIP_VALIDATOR)) { if (prAttr.isCategorical()) { validator = new CategoricalValidator.MembershipValidator(validatorType, prAttr); } } else if (validatorType.equals(ENSURE_INT_VALIDATOR)) { validator = new GenericValidator.EnsureIntValidator(validatorType, prAttr); } else if (validatorType.equals(ENSURE_LONG_VALIDATOR)) { validator = new GenericValidator.EnsureLongValidator(validatorType, prAttr); } else if (validatorType.equals(ENSURE_DOUBLE_VALIDATOR)) { validator = new GenericValidator.EnsureDoubleValidator(validatorType, prAttr); } else if (validatorType.equals(ENSURE_DATE_VALIDATOR)) { validator = new GenericValidator.EnsureDateValidator(validatorType, prAttr); } else if (validatorType.equals( ZCORE_BASED_RANGE_VALIDATOR)) { validator = new NumericalValidator.StatsBasedRangeValidator(validatorType, prAttr, validatorContext); } else if (validatorType.equals( ROBUST_ZCORE_BASED_RANGE_VALIDATOR)) { validator = new NumericalValidator.RobustZscoreBasedRangeValidator(validatorType, prAttr, validatorContext); } else { if (null == validatorConfig) { throw new IllegalStateException("missing HOCON configuration needed for custom validators"); } Config valConfig = getValidatorConfig(validatorConfig ,validatorType, prAttr); //custom validator with configured validator class names validator = createCustomValidator(validatorType, prAttr, valConfig); //custom validator factory if (null == validator && null != customValidatorFactory) { validator = customValidatorFactory.createValidator(validatorType, prAttr, valConfig); } if (null == validator) { throw new IllegalArgumentException("invalid val;idator type validator:" + validatorType + " ordinal:" + prAttr.getOrdinal() + " data type:" + prAttr.getDataType()); } } return validator; } /** * @param validatorType * @param prAttr * @param validatorConfig * @return */ private static Validator createCustomValidator(String validatorType, ProcessorAttribute prAttr, Config validatorConfig) { Validator validator = custValidators.get(validatorType); if (null == validator) { String validatorClass = custValidatorClasses.get("custom.validator.class." + validatorType); if (null != validatorClass) { try { Class<?> clazz = Class.forName(validatorClass); Constructor<?> ctor = clazz.getConstructor(String.class, prAttr.getClass(), Config.class); validator = (Validator)(ctor.newInstance(new Object[] { validatorType, prAttr, validatorConfig})); custValidators.put(validatorType, validator); } catch (Exception ex) { throw new IllegalArgumentException("could not create dynamic validator object for " + validatorType + " " + ex.getMessage()); } } } return validator; } /** * @param transformerConfig * @param validatorTag * @param prAttr * @return */ public static Config getValidatorConfig(Config validatorConfig ,String validatorTag, ProcessorAttribute prAttr) { Config valConfig = validatorConfig.getConfig("validators." + validatorTag); Config config = null; try { //attribute specific config config = null != valConfig ? valConfig.getConfig(prAttr.getName()) : null; } catch ( ConfigException.Missing ex) { } return null != config ? config : valConfig; } /** * @param validatotType * @return */ public static boolean isCustomValidator(String validatotType) { return custValidatorClasses.containsKey(validatotType); } /** * @param validatotType * @return */ public static boolean isStatBasedValidator(String validatotType) { return validatotType.equals(ZCORE_BASED_RANGE_VALIDATOR) || validatotType.equals(ROBUST_ZCORE_BASED_RANGE_VALIDATOR); } }