package org.datacite.mds.util;

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

import javax.persistence.NoResultException;
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;
import org.apache.log4j.Logger;
import org.datacite.mds.domain.Allocator;
import org.datacite.mds.domain.Datacentre;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;

/**
 * Class with several static util methods
 */
public class Utils {

    static Logger log = Logger.getLogger(Utils.class);

    /**
     * returns the prefix of a doi
     * 
     * @param doi
     *            Doi (e.g. "10.5072/foobar")
     * @return doi prefix (e.g. "10.5072")
     */
    public static String getDoiPrefix(String doi) {
        return doi.split("/")[0];
    }

    /**
     * returns the suffix of a doi
     * 
     * @param doi
     *            Doi (e.g. "10.5072/foobar")
     * @return doi prefix (e.g. "foobar")
     */
    public static String getDoiSuffix(String doi) {
        return doi.split("/")[1];
    }

    /**
     * converts a string with comma separated values to a List of Strings
     * 
     * @param csv
     *            comma separated values
     * @return List of Strings
     */
    public static List<String> csvToList(String csv) {
        if (csv == null) {
            csv = "";
        }
        return Arrays.asList(csv.split(","));
    }

    /**
     * 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 boolean isValid(Object object, String propertyName) {
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        Set violations = validator.validateProperty(object, propertyName);
        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 isConstraintValid(T object, Class<? extends Annotation> constraint) {
        ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
        Validator validator = validatorFactory.getValidator();
        Set<ConstraintViolation<T>> violations = validator.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;
    }

    public static String getHostname(String urlStr) {
        URL url;
        try {
            url = new URL(urlStr);
            String hostname = url.getHost();
            return hostname;
        } catch (MalformedURLException e) {
            return null;
        }

    }

    public static Object getCurrentUser() {
        log.debug("get current auth");
        Authentication currentAuth = SecurityContextHolder.getContext().getAuthentication();
        String symbol = currentAuth.getName();
        log.debug("search for '" + symbol + "'");
        try {
            Allocator al = Allocator.findAllocatorsBySymbolEquals(symbol).getSingleResult();
            log.debug("found allocator '" + symbol + "'");
            return al;
        } catch (Exception e) {
        }

        try {
            Datacentre dc = Datacentre.findDatacentresBySymbolEquals(symbol).getSingleResult();
            log.debug("found datacentre '" + symbol + "'");
            return dc;
        } catch (Exception e) {
        }

        log.debug("no allocator or datacentre found");

        return null;
    }

}

@@ -25,16 +25,45 @@
 .util;%0A%0A
+import java.io.StringWriter;%0A
 import j
@@ -229,52 +229,8 @@
 t;%0A%0A
-import javax.persistence.NoResultException;%0A
 impo
@@ -618,52 +618,120 @@
 org.
-springframework.security.core.Authentication
+dom4j.Document;%0Aimport org.dom4j.DocumentHelper;%0Aimport org.dom4j.io.OutputFormat;%0Aimport org.dom4j.io.XMLWriter
 ;%0Aim
@@ -773,24 +773,22 @@
 ore.
-GrantedAuthority
+Authentication
 ;%0Aim
@@ -858,16 +858,17 @@
 older;%0A%0A
+%0A
 /**%0A * C
@@ -5565,10 +5565,382 @@
 %0A    %7D%0A%0A
+    public static String formatXML(String xml) throws Exception %7B%0A        Document doc = DocumentHelper.parseText(xml);%0A        StringWriter sw = new StringWriter();%0A        OutputFormat format = OutputFormat.createPrettyPrint();%0A        XMLWriter xw = new XMLWriter(sw, format);%0A        xw.write(doc);%0A        String result = sw.toString();%0A        return result;%0A    %7D%0A%0A
 %7D%0A

add Utils.formatXML