package org.datacite.mds.validation.util;

import java.lang.annotation.Annotation;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Set;

import javax.validation.ConstraintValidatorContext;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;

import org.apache.commons.validator.UrlValidator;

public class ValidationUtils {
    
    private static Validator getValidator() {
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        return validator;
    }

    /**
     * Wrapper to simply validate a property of an object.
     * 
     * @param object
     *            object to validate
     * @param propertyName
     *            property to validate (e.g. field)
     * @return true if property validates
     * @see javax.validation.Validator.validateProperty
     */
    public static <T> boolean isValid(T object, String propertyName) {
        Set<?> violations = getValidator().validateProperty(object, propertyName);
        return violations.isEmpty();
    }

    /**
     * Wrapper to validate a an object.
     * 
     * @param object
     *            object to validate
     * @return true if object validates
     * @see javax.validation.Validator.validateProperty
     */
    public static <T> boolean isValid(T object) {
        Set<?> violations = getValidator().validate(object);
        return violations.isEmpty();
    }

    /**
     * Check if a specific constraint annotation is violated
     * 
     * @param object
     *            object to validate
     * @param constraint
     *            constraint annotation to be checked
     * @return true if the given constraint is not violated
     */
    public static <T> boolean isValid(T object, Class<? extends Annotation> constraint) {
        Set<ConstraintViolation<T>> violations = getValidator().validate(object);
    
        for (ConstraintViolation<T> violation : violations) {
            if (violation.getConstraintDescriptor().getAnnotation().annotationType().equals(constraint)) {
                return false;
            }
        }
    
        return true;
    }

    public static void addConstraintViolation(ConstraintValidatorContext context, String message, String node) {
        context.buildConstraintViolationWithTemplate(message).addNode(node).addConstraintViolation();
    }

    public static void addConstraintViolation(ConstraintValidatorContext context, String message) {
        context.buildConstraintViolationWithTemplate(message).addConstraintViolation();
    }

    public static boolean isHostname(String str) {
        try {
            URL url = new URL("http://" + str);
            if (!url.getHost().equals(str)) {
                // domain should only consists of the pure host name
                return false;
            }
    
            UrlValidator urlValidator = new UrlValidator();
            if (!urlValidator.isValid(url.toString())) {
                // url should be valid, e.g. "test.t" or "com" should be fail
                return false;
            }
        } catch (MalformedURLException ex) {
            // url should be well formed
            return false;
        }
        return true;
    }

}

@@ -72,24 +72,45 @@
 Annotation;%0A
+import java.net.IDN;%0A
 import java.
@@ -2997,32 +2997,329 @@
          %7D%0A    %0A
+            str = IDN.toASCII(str); // convert international domain names (IDN)%0A            if (str.matches(%22.*%5C%5C.xn--%5B%5E.%5D*$%22)) %7B%0A                // UrlValidator doesn't handle top level IDNs%0A                // so we add .org if necessary%0A                str += %22.org%22;%0A            %7D%0A            %0A
             UrlV
@@ -3404,22 +3404,23 @@
 lid(
-url.toString()
+%22http://%22 + str
 )) %7B
@@ -3534,32 +3534,32 @@
 ;%0A            %7D%0A
+
         %7D catch 
@@ -3559,28 +3559,16 @@
  catch (
-MalformedURL
 Exceptio

add support for IDNs (closes #MDS-226)