/*
 *  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.bval.jsr303.xml;


import java.io.InputStream;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.validation.Constraint;
import javax.validation.ConstraintValidator;
import javax.validation.Payload;
import javax.validation.ValidationException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;

import org.apache.bval.jsr303.ApacheValidatorFactory;
import org.apache.bval.jsr303.ConstraintAnnotationAttributes;
import org.apache.bval.jsr303.util.EnumerationConverter;
import org.apache.bval.jsr303.util.IOUtils;
import org.apache.bval.jsr303.util.SecureActions;
import org.apache.bval.util.FieldAccess;
import org.apache.bval.util.MethodAccess;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.Converter;
import org.apache.commons.lang3.StringUtils;


/**
 * Uses JAXB to parse constraints.xml based on validation-mapping-1.0.xsd.<br>
 */
@SuppressWarnings("restriction")
public class ValidationMappingParser {
    //    private static final Log log = LogFactory.getLog(ValidationMappingParser.class);
    private static final String VALIDATION_MAPPING_XSD = "META-INF/validation-mapping-1.0.xsd";

    private static final Set<ConstraintAnnotationAttributes> RESERVED_PARAMS = Collections.unmodifiableSet(EnumSet.of(
        ConstraintAnnotationAttributes.GROUPS, ConstraintAnnotationAttributes.MESSAGE,
        ConstraintAnnotationAttributes.PAYLOAD));

    private final Set<Class<?>> processedClasses;
    private final ApacheValidatorFactory factory;

    /**
     * Create a new ValidationMappingParser instance.
     * @param factory
     */
    public ValidationMappingParser(ApacheValidatorFactory factory) {
        this.factory = factory;
        this.processedClasses = new HashSet<Class<?>>();
    }

    /**
     * Parse files with constraint mappings and collect information in the factory.
     *  
     * @param xmlStreams - one or more contraints.xml file streams to parse
     */
    public void processMappingConfig(Set<InputStream> xmlStreams) throws ValidationException {
        for (InputStream xmlStream : xmlStreams) {
            ConstraintMappingsType mapping = parseXmlMappings(xmlStream);

            String defaultPackage = mapping.getDefaultPackage();
            processConstraintDefinitions(mapping.getConstraintDefinition(), defaultPackage);
            for (BeanType bean : mapping.getBean()) {
                Class<?> beanClass = loadClass(bean.getClazz(), defaultPackage);
                if (!processedClasses.add(beanClass)) {
                    // spec: A given class must not be described more than once amongst all
                    //  the XML mapping descriptors.
                    throw new ValidationException(
                          beanClass.getName() + " has already be configured in xml.");
                }
                factory.getAnnotationIgnores()
                      .setDefaultIgnoreAnnotation(beanClass, bean.isIgnoreAnnotations());
                processClassLevel(bean.getClassType(), beanClass, defaultPackage);
                processFieldLevel(bean.getField(), beanClass, defaultPackage);
                processPropertyLevel(bean.getGetter(), beanClass, defaultPackage);
                processedClasses.add(beanClass);
            }
        }
    }

    /** @param in XML stream to parse using the validation-mapping-1.0.xsd */
    private ConstraintMappingsType parseXmlMappings(InputStream in) {
        ConstraintMappingsType mappings;
        try {
            JAXBContext jc = JAXBContext.newInstance(ConstraintMappingsType.class);
            Unmarshaller unmarshaller = jc.createUnmarshaller();
            unmarshaller.setSchema(getSchema());
            StreamSource stream = new StreamSource(in);
            JAXBElement<ConstraintMappingsType> root =
                  unmarshaller.unmarshal(stream, ConstraintMappingsType.class);
            mappings = root.getValue();
        } catch (JAXBException e) {
            throw new ValidationException("Failed to parse XML deployment descriptor file.",
                  e);
        } finally {
            IOUtils.closeQuietly(in);
        }
        return mappings;
    }

    /** @return validation-mapping-1.0.xsd based schema */
    private Schema getSchema() {
        return ValidationParser.getSchema(VALIDATION_MAPPING_XSD);
    }

    private void processClassLevel(ClassType classType, Class<?> beanClass,
                                   String defaultPackage) {
        if (classType == null) {
            return;
        }

        // ignore annotation
        if (classType.isIgnoreAnnotations() != null) {
            factory.getAnnotationIgnores()
                  .setIgnoreAnnotationsOnClass(beanClass, classType.isIgnoreAnnotations());
        }

        // group sequence
        Class<?>[] groupSequence =
              createGroupSequence(classType.getGroupSequence(), defaultPackage);
        if (groupSequence != null) {
            factory.addDefaultSequence(beanClass, groupSequence);
        }

        // constraints
        for (ConstraintType constraint : classType.getConstraint()) {
            MetaConstraint<?, ?> metaConstraint =
                  createConstraint(constraint, beanClass, null, defaultPackage);
            factory.addMetaConstraint(beanClass, metaConstraint);
        }
    }

    @SuppressWarnings("unchecked")
    private <A extends Annotation, T> MetaConstraint<?, ?> createConstraint(
          ConstraintType constraint, Class<T> beanClass, Member member,
          String defaultPackage) {
        Class<A> annotationClass =
              (Class<A>) loadClass(constraint.getAnnotation(), defaultPackage);
        AnnotationProxyBuilder<A> annoBuilder = new AnnotationProxyBuilder<A>(annotationClass);

        if (constraint.getMessage() != null) {
            annoBuilder.setMessage(constraint.getMessage());
        }
        annoBuilder.setGroups(getGroups(constraint.getGroups(), defaultPackage));
        annoBuilder.setPayload(getPayload(constraint.getPayload(), defaultPackage));

        for (ElementType elementType : constraint.getElement()) {
            String name = elementType.getName();
            checkValidName(name);
            Class<?> returnType = getAnnotationParameterType(annotationClass, name);
            Object elementValue = getElementValue(elementType, returnType, defaultPackage);
            annoBuilder.putValue(name, elementValue);
        }
        return new MetaConstraint<T, A>(beanClass, member, annoBuilder.createAnnotation());
    }

    private void checkValidName(String name) {
        for (ConstraintAnnotationAttributes attr : RESERVED_PARAMS) {
            if (attr.getAttributeName().equals(name)) {
                throw new ValidationException(name + " is a reserved parameter name.");
            }
        }
    }

    private <A extends Annotation> Class<?> getAnnotationParameterType(
          final Class<A> annotationClass, final String name) {
        final Method m = doPrivileged(SecureActions.getPublicMethod(annotationClass, name));
        if (m == null) {
            throw new ValidationException("Annotation of type " + annotationClass.getName() +
                  " does not contain a parameter " + name + ".");
        }
        return m.getReturnType();
    }

    private Object getElementValue(ElementType elementType, Class<?> returnType,
                                   String defaultPackage) {
        removeEmptyContentElements(elementType);

        boolean isArray = returnType.isArray();
        if (!isArray) {
            if (elementType.getContent().size() != 1) {
                throw new ValidationException(
                      "Attempt to specify an array where single value is expected.");
            }
            return getSingleValue(elementType.getContent().get(0), returnType, defaultPackage);
        } else {
            List<Object> values = new ArrayList<Object>();
            for (Serializable s : elementType.getContent()) {
                values.add(getSingleValue(s, returnType.getComponentType(), defaultPackage));
            }
            return values.toArray(
                  (Object[]) Array.newInstance(returnType.getComponentType(), values.size()));
        }
    }

    private void removeEmptyContentElements(ElementType elementType) {
        List<Serializable> contentToDelete = new ArrayList<Serializable>();
        for (Serializable content : elementType.getContent()) {
            if (content instanceof String && ((String) content).matches("[\\n ].*")) {
                contentToDelete.add(content);
            }
        }
        elementType.getContent().removeAll(contentToDelete);
    }

    @SuppressWarnings("unchecked")
    private Object getSingleValue(Serializable serializable, Class<?> returnType,
                                  String defaultPackage) {

        Object returnValue;
        if (serializable instanceof String) {
            String value = (String) serializable;
            returnValue = convertToResultType(returnType, value, defaultPackage);
        } else if (serializable instanceof JAXBElement<?> &&
              ((JAXBElement<?>) serializable).getDeclaredType()
                    .equals(String.class)) {
            JAXBElement<?> elem = (JAXBElement<?>) serializable;
            String value = (String) elem.getValue();
            returnValue = convertToResultType(returnType, value, defaultPackage);
        } else if (serializable instanceof JAXBElement<?> &&
              ((JAXBElement<?>) serializable).getDeclaredType()
                    .equals(AnnotationType.class)) {
            JAXBElement<?> elem = (JAXBElement<?>) serializable;
            AnnotationType annotationType = (AnnotationType) elem.getValue();
            try {
                Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) returnType;
                returnValue =
                      createAnnotation(annotationType, annotationClass, defaultPackage);
            } catch (ClassCastException e) {
                throw new ValidationException("Unexpected parameter value");
            }
        } else {
            throw new ValidationException("Unexpected parameter value");
        }
        return returnValue;

    }

    private Object convertToResultType(Class<?> returnType, String value,
                                       String defaultPackage) {
        /**
         * Class is represented by the fully qualified class name of the class.
         * spec: Note that if the raw string is unqualified,
         * default package is taken into account.
         */
        if (returnType.equals(Class.class)) {
            value = toQualifiedClassName(value, defaultPackage);
        }

        /* Converter lookup */
        Converter converter = ConvertUtils.lookup(returnType);
        if (converter == null && returnType.isEnum()) {
            converter = EnumerationConverter.getInstance();
        }

        if (converter != null) {
            return converter.convert(returnType, value);
        } else {
            return converter;
        }
    }

    private <A extends Annotation> Annotation createAnnotation(AnnotationType annotationType,
                                                               Class<A> returnType,
                                                               String defaultPackage) {
        AnnotationProxyBuilder<A> metaAnnotation = new AnnotationProxyBuilder<A>(returnType);
        for (ElementType elementType : annotationType.getElement()) {
            String name = elementType.getName();
            Class<?> parameterType = getAnnotationParameterType(returnType, name);
            Object elementValue = getElementValue(elementType, parameterType, defaultPackage);
            metaAnnotation.putValue(name, elementValue);
        }
        return metaAnnotation.createAnnotation();
    }

    private Class<?>[] getGroups(GroupsType groupsType, String defaultPackage) {
        if (groupsType == null) {
            return new Class[]{};
        }

        List<Class<?>> groupList = new ArrayList<Class<?>>();
        for (JAXBElement<String> groupClass : groupsType.getValue()) {
            groupList.add(loadClass(groupClass.getValue(), defaultPackage));
        }
        return groupList.toArray(new Class[groupList.size()]);
    }


    @SuppressWarnings("unchecked")
    private Class<? extends Payload>[] getPayload(PayloadType payloadType,
                                                  String defaultPackage) {
        if (payloadType == null) {
            return new Class[]{};
        }

        List<Class<? extends Payload>> payloadList = new ArrayList<Class<? extends Payload>>();
        for (JAXBElement<String> groupClass : payloadType.getValue()) {
            Class<?> payload = loadClass(groupClass.getValue(), defaultPackage);
            if (!Payload.class.isAssignableFrom(payload)) {
                throw new ValidationException("Specified payload class " + payload.getName() +
                      " does not implement javax.validation.Payload");
            } else {
                payloadList.add((Class<? extends Payload>) payload);
            }
        }
        return payloadList.toArray(new Class[payloadList.size()]);
    }

    private Class<?>[] createGroupSequence(GroupSequenceType groupSequenceType,
                                               String defaultPackage) {
        if (groupSequenceType != null) {
            Class<?>[] groupSequence = new Class<?>[groupSequenceType.getValue().size()];
            int i=0;
            for (JAXBElement<String> groupName : groupSequenceType.getValue()) {
                Class<?> group = loadClass(groupName.getValue(), defaultPackage);
                groupSequence[i++] = group;
            }
            return groupSequence;
        } else {
            return null;
        }
    }

    private void processFieldLevel(List<FieldType> fields, Class<?> beanClass,
                                   String defaultPackage) {
        List<String> fieldNames = new ArrayList<String>();
        for (FieldType fieldType : fields) {
            String fieldName = fieldType.getName();
            if (fieldNames.contains(fieldName)) {
                throw new ValidationException(fieldName +
                      " is defined more than once in mapping xml for bean " +
                      beanClass.getName());
            } else {
                fieldNames.add(fieldName);
            }
            final Field field = doPrivileged(SecureActions.getDeclaredField(beanClass, fieldName));
            if (field == null) {
                throw new ValidationException(
                      beanClass.getName() + " does not contain the fieldType  " + fieldName);
            }

            // ignore annotations
            boolean ignoreFieldAnnotation = fieldType.isIgnoreAnnotations() == null ? false :
                  fieldType.isIgnoreAnnotations();
            if (ignoreFieldAnnotation) {
                factory.getAnnotationIgnores().setIgnoreAnnotationsOnMember(field);
            }

            // valid
            if (fieldType.getValid() != null) {
                factory.addValid(beanClass, new FieldAccess(field));
            }

            // constraints
            for (ConstraintType constraintType : fieldType.getConstraint()) {
                MetaConstraint<?, ?> constraint =
                      createConstraint(constraintType, beanClass, field, defaultPackage);
                factory.addMetaConstraint(beanClass, constraint);
            }
        }
    }

    private void processPropertyLevel(List<GetterType> getters, Class<?> beanClass,
                                      String defaultPackage) {
        List<String> getterNames = new ArrayList<String>();
        for (GetterType getterType : getters) {
            String getterName = getterType.getName();
            if (getterNames.contains(getterName)) {
                throw new ValidationException(getterName +
                      " is defined more than once in mapping xml for bean " +
                      beanClass.getName());
            } else {
                getterNames.add(getterName);
            }
            final Method method = getGetter(beanClass, getterName);
            if (method == null) {
                throw new ValidationException(
                      beanClass.getName() + " does not contain the property  " + getterName);
            }

            // ignore annotations
            boolean ignoreGetterAnnotation = getterType.isIgnoreAnnotations() == null ? false :
                  getterType.isIgnoreAnnotations();
            if (ignoreGetterAnnotation) {
                factory.getAnnotationIgnores().setIgnoreAnnotationsOnMember(method);
            }

            // valid
            if (getterType.getValid() != null) {
                factory.addValid(beanClass, new MethodAccess(getterName, method));
            }

            // constraints
            for (ConstraintType constraintType : getterType.getConstraint()) {
                MetaConstraint<?, ?> metaConstraint =
                      createConstraint(constraintType, beanClass, method, defaultPackage);
                factory.addMetaConstraint(beanClass, metaConstraint);
            }
        }
    }

    @SuppressWarnings("unchecked")
    private void processConstraintDefinitions(
          List<ConstraintDefinitionType> constraintDefinitionList, String defaultPackage) {
        for (ConstraintDefinitionType constraintDefinition : constraintDefinitionList) {
            String annotationClassName = constraintDefinition.getAnnotation();

            Class<?> clazz = loadClass(annotationClassName, defaultPackage);
            if (!clazz.isAnnotation()) {
                throw new ValidationException(annotationClassName + " is not an annotation");
            }
            Class<? extends Annotation> annotationClass = (Class<? extends Annotation>) clazz;

            ValidatedByType validatedByType = constraintDefinition.getValidatedBy();
            List<Class<? extends ConstraintValidator<?, ?>>> classes =
                new ArrayList<Class<? extends ConstraintValidator<?, ?>>>();
            /*
             If include-existing-validator is set to false,
             ConstraintValidator defined on the constraint annotation are ignored.
              */
            if (validatedByType.isIncludeExistingValidators() != null &&
                  validatedByType.isIncludeExistingValidators()) {
                /*
                 If set to true, the list of ConstraintValidators described in XML
                 are concatenated to the list of ConstraintValidator described on the
                 annotation to form a new array of ConstraintValidator evaluated.
                 */
                classes.addAll(findConstraintValidatorClasses(annotationClass));
            }
            for (JAXBElement<String> validatorClassName : validatedByType.getValue()) {
                Class<? extends ConstraintValidator<?, ?>> validatorClass;
                validatorClass = (Class<? extends ConstraintValidator<?, ?>>)
                      loadClass(validatorClassName.getValue());


                if (!ConstraintValidator.class.isAssignableFrom(validatorClass)) {
                    throw new ValidationException(
                          validatorClass + " is not a constraint validator class");
                }

                /*
                Annotation based ConstraintValidator come before XML based
                ConstraintValidator in the array. The new list is returned
                by ConstraintDescriptor.getConstraintValidatorClasses().
                 */
                if (!classes.contains(validatorClass)) classes.add(validatorClass);
            }
            if (factory.getConstraintsCache().containsConstraintValidator(annotationClass)) {
                throw new ValidationException("Constraint validator for " +
                      annotationClass.getName() + " already configured.");
            } else {
                factory.getConstraintsCache().putConstraintValidator(annotationClass,
                      classes.toArray(new Class[classes.size()]));
            }
        }
    }

    private List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> findConstraintValidatorClasses(
          Class<? extends Annotation> annotationType) {
        List<Class<? extends ConstraintValidator<? extends Annotation, ?>>> classes =
              new ArrayList<Class<? extends ConstraintValidator<? extends Annotation, ?>>>();

        Class<? extends ConstraintValidator<?, ?>>[] validator =
              factory.getDefaultConstraints().getValidatorClasses(annotationType);
        if (validator != null) {
            classes
                  .addAll(Arrays.asList(validator));
        } else {
            Class<? extends ConstraintValidator<?, ?>>[] validatedBy = annotationType
                  .getAnnotation(Constraint.class)
                  .validatedBy();
            classes.addAll(Arrays.asList(validatedBy));
        }
        return classes;
    }

    private Class<?> loadClass(String className, String defaultPackage) {
        return loadClass(toQualifiedClassName(className, defaultPackage));
    }

    private String toQualifiedClassName(String className, String defaultPackage) {
        if (!isQualifiedClass(className)) {
            className = defaultPackage + "." + className;
        }
        return className;
    }

    private boolean isQualifiedClass(String clazz) {
        return clazz.contains(".");
    }



    private static <T> T doPrivileged(final PrivilegedAction<T> action) {
        if (System.getSecurityManager() != null) {
            return AccessController.doPrivileged(action);
        } else {
            return action.run();
        }
    }



    private static Method getGetter(final Class<?> clazz, final String propertyName) {
        return doPrivileged(new PrivilegedAction<Method>() {
            public Method run() {
                try {
                    final String p = StringUtils.capitalize(propertyName);
                    try {
                        return clazz.getMethod("get" + p);
                    } catch (NoSuchMethodException e) {
                        return clazz.getMethod("is" + p);
                    }
                } catch (NoSuchMethodException e) {
                    return null;
                }
            }
        });

    }



    private Class<?> loadClass(final String className) {
        ClassLoader loader = doPrivileged(SecureActions.getContextClassLoader());
        if (loader == null)
            loader = getClass().getClassLoader();

        try {
            return Class.forName(className, true, loader);
        } catch (ClassNotFoundException ex) {
            throw new ValidationException("Unable to load class: " + className, ex);
        }
    }

}
