/**
 * 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.storm.validation;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.storm.Config;
import org.apache.storm.utils.Utils;
import org.apache.storm.validation.ConfigValidationAnnotations.ValidatorParams;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Provides functionality for validating configuration fields.
 */
public class ConfigValidation {
    private static final Logger LOG = LoggerFactory.getLogger(ConfigValidation.class);
    //We follow the model of service loaders (Even though it is not a service).
    private static final String CONFIG_CLASSES_NAME = "META-INF/services/" + Validated.class.getName();

    /*
     * Validator definitions
     */
    //The following come from the JVm Specification table 4.4
    // https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.5
    private static final int ACC_PUBLIC = 0x0001;
    private static final int ACC_STATIC = 0x0008;
    private static final int ACC_FINAL = 0x0010;
    private static final int DESIRED_FIELD_ACC = ACC_PUBLIC | ACC_STATIC | ACC_FINAL;
    private static List<Class<?>> configClasses = null;

    public static synchronized List<Class<?>> getConfigClasses() {
        if (configClasses == null) {
            List<Class<?>> ret = new ArrayList<>();
            Set<String> classesToScan = new HashSet<>();
            classesToScan.add(Config.class.getName());
            for (URL url : Utils.findResources(CONFIG_CLASSES_NAME)) {
                try {
                    try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()))) {
                        String line;
                        while ((line = in.readLine()) != null) {
                            line = line.replaceAll("#.*$", "").trim();
                            if (!line.isEmpty()) {
                                classesToScan.add(line);
                            }
                        }
                    }
                } catch (IOException e) {
                    throw new RuntimeException("Error trying to read " + url, e);
                }
            }
            for (String clazz : classesToScan) {
                try {
                    ret.add(Class.forName(clazz));
                } catch (ClassNotFoundException e) {
                    throw new RuntimeException(e);
                }
            }
            LOG.debug("Will use {} for validation", ret);
            configClasses = ret;
        }
        return configClasses;
    }

    /**
     * Validates a field given field name as string uses Config.java as the default config class
     *
     * @param fieldName provided as a string
     * @param conf      map of confs
     */
    public static void validateField(String fieldName, Map<String, Object> conf) {
        validateField(fieldName, conf, getConfigClasses());
    }

    /**
     * Validates a field given field name as string.
     *
     * @param fieldName provided as a string
     * @param conf      map of confs
     * @param configs   config class
     */
    public static void validateField(String fieldName, Map<String, Object> conf, List<Class<?>> configs) {
        Field field = null;
        for (Class<?> clazz : configs) {
            try {
                field = clazz.getField(fieldName);
            } catch (NoSuchFieldException e) {
                //Ignored
            }
        }
        if (field == null) {
            throw new RuntimeException("Could not find " + fieldName + " in any of " + configs);
        }
        validateField(field, conf);
    }

    /**
     * Validates a field given field.  Calls correct ValidatorField method based on which fields are declared for the corresponding
     * annotation.
     *
     * @param field field that needs to be validated
     * @param conf  map of confs
     */
    public static void validateField(Field field, Map<String, Object> conf) {
        Annotation[] annotations = field.getAnnotations();
        if (annotations.length == 0) {
            LOG.warn("Field {} does not have validator annotation", field);
        }
        try {
            for (Annotation annotation : annotations) {
                if (annotation.annotationType().equals(Deprecated.class)) {
                    LOG.warn("{} is a deprecated config please see {}.{} for more information.",
                             field.get(null), field.getDeclaringClass(), field.getName());
                    continue;
                }
                String type = annotation.annotationType().getName();
                Class<?> validatorClass = null;
                Class<?>[] classes = ConfigValidationAnnotations.class.getDeclaredClasses();
                //check if annotation is one of our
                for (Class<?> clazz : classes) {
                    if (clazz.getName().equals(type)) {
                        validatorClass = clazz;
                        break;
                    }
                }
                if (validatorClass != null) {
                    Object v = validatorClass.cast(annotation);
                    String key = (String) field.get(null);
                    @SuppressWarnings("unchecked")
                    Class<Validator> clazz = (Class<Validator>) validatorClass
                        .getMethod(ConfigValidationAnnotations.ValidatorParams.VALIDATOR_CLASS).invoke(v);
                    Validator o = null;
                    Map<String, Object> params = getParamsFromAnnotation(validatorClass, v);
                    //two constructor signatures used to initialize validators.
                    //One constructor takes input a Map of arguments, the other doesn't take any arguments (default constructor)
                    //If validator has a constructor that takes a Map as an argument call that constructor
                    if (hasConstructor(clazz, Map.class)) {
                        o = clazz.getConstructor(Map.class).newInstance(params);
                    } else { //If not call default constructor
                        o = clazz.newInstance();
                    }
                    o.validateField(field.getName(), conf.get(key));
                }
            }
        } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Validate topology conf.
     * @param topoConf The topology conf.
     */
    public static void validateTopoConf(Map<String, Object> topoConf) {
        validateFields(topoConf, Arrays.asList(Config.class));
    }

    /**
     * Validate all confs in map.
     *
     * @param conf map of configs
     */
    public static void validateFields(Map<String, Object> conf) {
        validateFields(conf, getConfigClasses());
    }

    /**
     * Validate all confs in map.
     *
     * @param conf    map of configs
     * @param classes config class
     */
    public static void validateFields(Map<String, Object> conf, List<Class<?>> classes) {
        for (Class<?> clazz : classes) {
            for (Field field : clazz.getDeclaredFields()) {
                if (!isFieldAllowed(field)) {
                    continue;
                }
                Object keyObj = null;
                try {
                    keyObj = field.get(null);
                } catch (IllegalAccessException e) {
                    //This should not happen because we checked for PUBLIC in isFieldAllowed
                    throw new RuntimeException(e);
                }
                //make sure that defined key is string in case wrong stuff got put into Config.java
                if (keyObj instanceof String) {
                    String confKey = (String) keyObj;
                    if (conf.containsKey(confKey)) {
                        validateField(field, conf);
                    }
                }
            }
        }
    }

    public static boolean isFieldAllowed(Field field) {
        return field.getAnnotation(NotConf.class) == null
               && String.class.equals(field.getType())
               && ((field.getModifiers() & DESIRED_FIELD_ACC) == DESIRED_FIELD_ACC) && !field.isSynthetic();
    }

    private static Map<String, Object> getParamsFromAnnotation(Class<?> validatorClass, Object v)
        throws InvocationTargetException, IllegalAccessException {
        Map<String, Object> params = new HashMap<String, Object>();
        for (Method method : validatorClass.getDeclaredMethods()) {

            Object value = null;
            try {
                value = (Object) method.invoke(v);
            } catch (IllegalArgumentException ex) {
                value = null;
            }
            if (value != null) {
                params.put(method.getName(), value);
            }
        }
        return params;
    }

    private static boolean hasConstructor(Class<?> clazz, Class<?> paramClass) {
        Class<?>[] classes = { paramClass };
        try {
            clazz.getConstructor(classes);
        } catch (NoSuchMethodException e) {
            return false;
        }
        return true;
    }

    public abstract static class Validator {
        public Validator(Map<String, Object> params) {
        }

        public Validator() {
        }

        public abstract void validateField(String name, Object o);
    }

    /**
     * Validates if an object is not null.
     */

    public static class NotNullValidator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                throw new IllegalArgumentException("Field " + name + "cannot be null! Actual value: " + o);
            }
        }
    }

    /**
     * Validates basic types.
     */
    public static class SimpleTypeValidator extends Validator {

        private Class<?> type;

        public SimpleTypeValidator(Map<String, Object> params) {
            this.type = (Class<?>) params.get(ConfigValidationAnnotations.ValidatorParams.TYPE);
        }

        public static void validateField(String name, Class<?> type, Object o) {
            if (o == null) {
                return;
            }
            if (type.isInstance(o)) {
                return;
            }
            throw new IllegalArgumentException(
                "Field " + name + " must be of type " + type + ". Object: " + o + " actual type: " + o.getClass());
        }

        @Override
        public void validateField(String name, Object o) {
            validateField(name, this.type, o);
        }
    }

    /**
     * Checks if the named type derives from the specified Class.
     */
    public static class DerivedTypeValidator extends Validator {

        private Class<?> baseType;

        public DerivedTypeValidator(Map<String, Object> params) {
            this.baseType = (Class<?>) params.get(ValidatorParams.BASE_TYPE);
        }

        public static void validateField(String name, Class<?> baseType, Object actualTypeName) {
            if (actualTypeName == null) {
                return;
            }
            try {
                Class<?> actualType = Class.forName(actualTypeName.toString());
                if (baseType.isAssignableFrom(actualType)) {
                    return;
                }
                throw new IllegalArgumentException(
                    "Field " + name + " must represent a type that derives from '" + baseType + "'. Specified type = " + actualTypeName);
            } catch (ClassNotFoundException e) {
                throw new IllegalArgumentException(e.getMessage());
            }
        }

        @Override
        public void validateField(String name, Object actualTypeName) {
            validateField(name, this.baseType, actualTypeName);
        }
    }

    public static class StringValidator extends Validator {

        private HashSet<String> acceptedValues = null;

        public StringValidator() {
        }

        public StringValidator(Map<String, Object> params) {

            this.acceptedValues =
                new HashSet<String>(Arrays.asList((String[]) params.get(ConfigValidationAnnotations.ValidatorParams.ACCEPTED_VALUES)));

            if (this.acceptedValues.isEmpty() || (this.acceptedValues.size() == 1 && this.acceptedValues.contains(""))) {
                this.acceptedValues = null;
            }
        }

        @Override
        public void validateField(String name, Object o) {
            SimpleTypeValidator.validateField(name, String.class, o);
            if (this.acceptedValues != null) {
                if (!this.acceptedValues.contains((String) o)) {
                    throw new IllegalArgumentException(
                        "Field " + name + " is not an accepted value. Value: " + o + " Accepted values: " + this.acceptedValues);
                }
            }
        }
    }

    public static class BooleanValidator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            SimpleTypeValidator.validateField(name, Boolean.class, o);
        }
    }

    public static class NumberValidator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            SimpleTypeValidator.validateField(name, Number.class, o);
        }
    }

    public static class DoubleValidator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            SimpleTypeValidator.validateField(name, Double.class, o);
        }
    }

    /**
     * Validates a Integer.
     */
    public static class IntegerValidator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            validateInteger(name, o);
        }

        public void validateInteger(String name, Object o) {
            if (o == null) {
                return;
            }
            final long i;
            if (o instanceof Number
                && (i = ((Number) o).longValue()) == ((Number) o).doubleValue()) {
                if (i <= Integer.MAX_VALUE && i >= Integer.MIN_VALUE) {
                    return;
                }
            }
            throw new IllegalArgumentException("Field " + name + " must be an Integer within type range.");
        }
    }

    /**
     * Validates an entry for ImpersonationAclUser.
     */
    public static class ImpersonationAclUserEntryValidator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                return;
            }
            ConfigValidationUtils.NestableFieldValidator validator =
                ConfigValidationUtils.mapFv(ConfigValidationUtils.fv(String.class, false),
                                            ConfigValidationUtils.listFv(String.class, false), false);
            validator.validateField(name, o);
            @SuppressWarnings("unchecked")
            Map<String, List<String>> mapObject = (Map<String, List<String>>) o;
            if (!mapObject.containsKey("hosts")) {
                throw new IllegalArgumentException(name + " should contain Map entry with key: hosts");
            }
            if (!mapObject.containsKey("groups")) {
                throw new IllegalArgumentException(name + " should contain Map entry with key: groups");
            }
        }
    }

    /**
     * validates a list of has no duplicates.
     */
    public static class NoDuplicateInListValidator extends Validator {

        @Override
        public void validateField(String name, Object field) {
            if (field == null) {
                return;
            }
            //check if iterable
            SimpleTypeValidator.validateField(name, Iterable.class, field);
            HashSet<Object> objectSet = new HashSet<Object>();
            for (Object o : (Iterable<?>) field) {
                if (objectSet.contains(o)) {
                    throw new IllegalArgumentException(name + " should contain no duplicate elements. Duplicated element: " + o);
                }
                objectSet.add(o);
            }
        }
    }

    /**
     * Validates a String or a list of Strings.
     */
    public static class StringOrStringListValidator extends Validator {

        private ConfigValidationUtils.FieldValidator fv = ConfigValidationUtils.listFv(String.class, false);

        @Override
        public void validateField(String name, Object o) {

            if (o == null || o instanceof String) {
                // A null value or a String value is acceptable
                return;
            }
            this.fv.validateField(name, o);
        }
    }

    /**
     * Validates Kryo Registration.
     */
    public static class KryoRegValidator extends Validator {

        @SuppressWarnings("unchecked")
        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                return;
            }
            if (o instanceof Iterable) {
                for (Object e : (Iterable<?>) o) {
                    if (e instanceof Map) {
                        for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) e).entrySet()) {
                            if (!(entry.getKey() instanceof String)
                                || !(entry.getValue() instanceof String)) {
                                throw new IllegalArgumentException(
                                    "Each element of the list " + name + " must be a String or a Map of Strings");
                            }
                        }
                    } else if (!(e instanceof String)) {
                        throw new IllegalArgumentException(
                            "Each element of the list " + name + " must be a String or a Map of Strings");
                    }
                }
                return;
            }
            throw new IllegalArgumentException(
                "Field " + name + " must be an Iterable containing only Strings or Maps of Strings");
        }
    }

    /*
     * Methods for validating confs
     */

    /**
     * Validates if a number is a power of 2.
     */
    public static class PowerOf2Validator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                return;
            }
            final long i;
            if (o instanceof Number
                && (i = ((Number) o).longValue()) == ((Number) o).doubleValue()) {
                // Test whether the integer is a power of 2.
                if (i > 0 && (i & (i - 1)) == 0) {
                    return;
                }
            }
            throw new IllegalArgumentException("Field " + name + " must be a power of 2.");
        }
    }

    /**
     * Validates each entry in a list.
     */
    public static class ListEntryTypeValidator extends Validator {

        private Class<?> type;

        public ListEntryTypeValidator(Map<String, Object> params) {
            this.type = (Class<?>) params.get(ConfigValidationAnnotations.ValidatorParams.TYPE);
        }

        public static void validateField(String name, Class<?> type, Object o) {
            ConfigValidationUtils.NestableFieldValidator validator = ConfigValidationUtils.listFv(type, false);
            validator.validateField(name, o);
        }

        @Override
        public void validateField(String name, Object o) {
            validateField(name, this.type, o);
        }
    }

    /**
     * Validates each entry in a list against a list of custom Validators. Each validator in the list of validators must inherit or be an
     * instance of Validator class
     */
    public static class ListEntryCustomValidator extends Validator {

        private Class<?>[] entryValidators;

        public ListEntryCustomValidator(Map<String, Object> params) {
            this.entryValidators = (Class<?>[]) params.get(ConfigValidationAnnotations.ValidatorParams.ENTRY_VALIDATOR_CLASSES);
        }

        public static void validateField(String name, Class<?>[] validators, Object o)
            throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
            if (o == null) {
                return;
            }
            //check if iterable
            SimpleTypeValidator.validateField(name, Iterable.class, o);
            for (Object entry : (Iterable<?>) o) {
                for (Class<?> validator : validators) {
                    Object v = validator.getConstructor().newInstance();
                    if (v instanceof Validator) {
                        ((Validator) v).validateField(name + " list entry", entry);
                    } else {
                        LOG.warn(
                            "validator: {} cannot be used in ListEntryCustomValidator.  Individual entry validators must a instance of "
                                    + "Validator class",
                            validator.getName());
                    }
                }
            }
        }

        @Override
        public void validateField(String name, Object o) {
            try {
                validateField(name, this.entryValidators, o);
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException | InstantiationException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * validates each key and value in a map of a certain type.
     */
    public static class MapEntryTypeValidator extends Validator {

        private Class<?> keyType;
        private Class<?> valueType;

        public MapEntryTypeValidator(Map<String, Object> params) {
            this.keyType = (Class<?>) params.get(ConfigValidationAnnotations.ValidatorParams.KEY_TYPE);
            this.valueType = (Class<?>) params.get(ConfigValidationAnnotations.ValidatorParams.VALUE_TYPE);
        }

        public static void validateField(String name, Class<?> keyType, Class<?> valueType, Object o) {
            ConfigValidationUtils.NestableFieldValidator validator = ConfigValidationUtils.mapFv(keyType, valueType, false);
            validator.validateField(name, o);
        }

        @Override
        public void validateField(String name, Object o) {
            validateField(name, this.keyType, this.valueType, o);
        }
    }

    /**
     * validates each key and each value against the respective arrays of validators.
     */
    public static class MapEntryCustomValidator extends Validator {

        private Class<?>[] keyValidators;
        private Class<?>[] valueValidators;

        public MapEntryCustomValidator(Map<String, Object> params) {
            this.keyValidators = (Class<?>[]) params.get(ConfigValidationAnnotations.ValidatorParams.KEY_VALIDATOR_CLASSES);
            this.valueValidators = (Class<?>[]) params.get(ConfigValidationAnnotations.ValidatorParams.VALUE_VALIDATOR_CLASSES);
        }

        @SuppressWarnings("unchecked")
        public static void validateField(String name, Class<?>[] keyValidators, Class<?>[] valueValidators, Object o)
            throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
            if (o == null) {
                return;
            }
            //check if Map
            SimpleTypeValidator.validateField(name, Map.class, o);
            for (Map.Entry<Object, Object> entry : ((Map<Object, Object>) o).entrySet()) {
                for (Class<?> kv : keyValidators) {
                    Object keyValidator = kv.getConstructor().newInstance();
                    if (keyValidator instanceof Validator) {
                        ((Validator) keyValidator).validateField(name + " Map key", entry.getKey());
                    } else {
                        LOG.warn(
                            "validator: {} cannot be used in MapEntryCustomValidator to validate keys.  Individual entry validators must "
                                    + "a instance of Validator class",
                            kv.getName());
                    }
                }
                for (Class<?> vv : valueValidators) {
                    Object valueValidator = vv.getConstructor().newInstance();
                    if (valueValidator instanceof Validator) {
                        ((Validator) valueValidator).validateField(name + " Map value", entry.getValue());
                    } else {
                        LOG.warn(
                            "validator: {} cannot be used in MapEntryCustomValidator to validate values.  Individual entry validators "
                                    + "must a instance of Validator class",
                            vv.getName());
                    }
                }
            }
        }

        @Override
        public void validateField(String name, Object o) {
            try {
                validateField(name, this.keyValidators, this.valueValidators, o);
            } catch (IllegalAccessException | InstantiationException | NoSuchMethodException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * Validates a positive number.
     */
    public static class PositiveNumberValidator extends Validator {

        private boolean includeZero;

        public PositiveNumberValidator() {
            this.includeZero = false;
        }

        public PositiveNumberValidator(Map<String, Object> params) {
            this.includeZero = (boolean) params.get(ConfigValidationAnnotations.ValidatorParams.INCLUDE_ZERO);
        }

        public static void validateField(String name, boolean includeZero, Object o) {
            if (o == null) {
                return;
            }
            if (o instanceof Number) {
                if (includeZero) {
                    if (((Number) o).doubleValue() >= 0.0) {
                        return;
                    }
                } else {
                    if (((Number) o).doubleValue() > 0.0) {
                        return;
                    }
                }
            }
            throw new IllegalArgumentException("Field " + name + " must be a Positive Number");
        }

        @Override
        public void validateField(String name, Object o) {
            validateField(name, this.includeZero, o);
        }
    }

    public static class ClusterMetricRegistryValidator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                return;
            }
            SimpleTypeValidator.validateField(name, Map.class, o);
            if (!((Map<?, ?>) o).containsKey("class")) {
                throw new IllegalArgumentException("Field " + name + " must have map entry with key: class");
            }

            SimpleTypeValidator.validateField(name, String.class, ((Map<?, ?>) o).get("class"));
        }
    }

    public static class MetricRegistryValidator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                return;
            }
            SimpleTypeValidator.validateField(name, Map.class, o);
            if (!((Map<?, ?>) o).containsKey("class")) {
                throw new IllegalArgumentException("Field " + name + " must have map entry with key: class");
            }
            if (!((Map<?, ?>) o).containsKey("parallelism.hint")) {
                throw new IllegalArgumentException("Field " + name + " must have map entry with key: parallelism.hint");
            }

            SimpleTypeValidator.validateField(name, String.class, ((Map<?, ?>) o).get("class"));
            new IntegerValidator().validateField(name, ((Map<?, ?>) o).get("parallelism.hint"));
        }
    }

    public static class MetricReportersValidator extends Validator {
        private static final String NIMBUS = "nimbus";
        private static final String SUPERVISOR = "supervisor";
        private static final String WORKER = "worker";
        private static final String CLASS = "class";
        private static final String FILTER = "filter";
        private static final String DAEMONS = "daemons";

        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                return;
            }
            SimpleTypeValidator.validateField(name, Map.class, o);
            if (!((Map) o).containsKey(CLASS)) {
                throw new IllegalArgumentException("Field " + name + " must have map entry with key: class");
            }
            if (!((Map) o).containsKey(DAEMONS)) {
                throw new IllegalArgumentException("Field " + name + " must have map entry with key: daemons");
            } else {
                // daemons can only be 'nimbus', 'supervisor', or 'worker'
                Object list = ((Map) o).get(DAEMONS);
                if (!(list instanceof List)) {
                    throw new IllegalArgumentException("Field 'daemons' must be a non-null list.");
                }
                List daemonList = (List) list;
                for (Object string : daemonList) {
                    if (string instanceof String
                        && (string.equals(NIMBUS) || string.equals(SUPERVISOR) || string.equals(WORKER))) {
                        continue;
                    }
                    throw new IllegalArgumentException("Field 'daemons' must contain at least one of the following:"
                                                       + " \"nimbus\", \"supervisor\", or \"worker\"");
                }

            }
            if (((Map) o).containsKey(FILTER)) {
                Map filterMap = (Map) ((Map) o).get(FILTER);
                SimpleTypeValidator.validateField(CLASS, String.class, filterMap.get(CLASS));
            }
            SimpleTypeValidator.validateField(name, String.class, ((Map) o).get(CLASS));
        }
    }

    public static class EventLoggerRegistryValidator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                return;
            }
            SimpleTypeValidator.validateField(name, Map.class, o);
            if (!((Map<?, ?>) o).containsKey("class")) {
                throw new IllegalArgumentException("Field " + name + " must have map entry with key: class");
            }

            SimpleTypeValidator.validateField(name, String.class, ((Map<?, ?>) o).get("class"));

            if (((Map<?, ?>) o).containsKey("arguments")) {
                SimpleTypeValidator.validateField(name, Map.class, ((Map<?, ?>) o).get("arguments"));
            }
        }
    }

    public static class MapOfStringToMapOfStringToObjectValidator extends Validator {
        @Override
        public void validateField(String name, Object o) {
            ConfigValidationUtils.NestableFieldValidator validator =
                ConfigValidationUtils.mapFv(ConfigValidationUtils.fv(String.class, false),
                                            ConfigValidationUtils.mapFv(String.class, Object.class, true), true);
            validator.validateField(name, o);
        }
    }

    public static class PacemakerAuthTypeValidator extends Validator {
        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                throw new IllegalArgumentException("Field " + name + " must be set.");
            }

            if (o instanceof String
                && (((String) o).equals("NONE") || ((String) o).equals("DIGEST")
                    || ((String) o).equals("KERBEROS"))) {
                return;
            }
            throw new IllegalArgumentException("Field " + name + " must be one of \"NONE\", \"DIGEST\", or \"KERBEROS\"");
        }
    }

    public static class UserResourcePoolEntryValidator extends Validator {

        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                return;
            }
            SimpleTypeValidator.validateField(name, Map.class, o);
            Map<?, ?> m = (Map<?, ?>) o;
            if (!m.containsKey("cpu")) {
                throw new IllegalArgumentException("Field " + name + " must have map entry with key: cpu");
            }
            if (!m.containsKey("memory")) {
                throw new IllegalArgumentException("Field " + name + " must have map entry with key: memory");
            }

            SimpleTypeValidator.validateField(name, Number.class, m.get("cpu"));
            SimpleTypeValidator.validateField(name, Number.class, m.get("memory"));
        }
    }

    public static class ImplementsClassValidator extends Validator {

        Class<?> classImplements;

        public ImplementsClassValidator(Map<String, Object> params) {
            this.classImplements = (Class<?>) params.get(ConfigValidationAnnotations.ValidatorParams.IMPLEMENTS_CLASS);
        }

        @Override
        public void validateField(String name, Object o) {
            if (o == null) {
                return;
            }
            SimpleTypeValidator.validateField(name, String.class, o);
            String className = (String) o;
            try {
                Class<?> objectClass = Class.forName(className);
                if (!this.classImplements.isAssignableFrom(objectClass)) {
                    throw new IllegalArgumentException("Field " + name + " with value " + o
                                                       + " does not implement " + this.classImplements.getName());
                }
            } catch (ClassNotFoundException e) {
                //To support topologies of older version to run, we might have to loose the constraints so that
                //the configs of older version can pass the validation.
                if (className.startsWith("backtype.storm")) {
                    LOG.error("ClassNotFoundException: {}", className);
                    LOG.warn("Replace backtype.storm with org.apache.storm and try to validate again");
                    LOG.warn("We loosen some constraints here to support topologies of older version running on the current version");
                    validateField(name, className.replace("backtype.storm", "org.apache.storm"));
                } else {
                    throw new RuntimeException("Failed to validate config " + name + " with value " + className, e);
                }
            }
        }
    }

    /**
     * Validates a list of a list of Strings.
     */
    public static class ListOfListOfStringValidator extends Validator {

        @Override
        public void validateField(String name, Object o) throws IllegalArgumentException {
            if (o == null) {
                return;
            }
            if (o instanceof List) {
                for (Object entry1 : (List) o) {
                    if (entry1 instanceof List) {
                        for (Object entry2 : (List) entry1) {
                            if (!(entry2 instanceof String)) {
                                throw new IllegalArgumentException(
                                    "Field " + name + " must be an Iterable containing only List of List of Strings");
                            }
                        }
                    } else {
                        throw new IllegalArgumentException(
                            "Field " + name + " must be an Iterable containing only List of List of Strings");
                    }
                }
            } else {
                throw new IllegalArgumentException(
                    "Field " + name + " must be an Iterable containing only List of List of Strings");
            }
        }
    }
}
