package org.datacite.mds.test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.util.HashSet;
import java.util.Set;

import org.datacite.mds.domain.Allocator;
import org.datacite.mds.domain.AllocatorOrDatacentre;
import org.datacite.mds.domain.Datacentre;
import org.datacite.mds.domain.Dataset;
import org.datacite.mds.domain.Prefix;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;

public abstract class TestUtils {

    /**
     * call a constructor of a given class even if it's private.
     * 
     * @param cls
     */
    public static void callConstructor(final Class<?> cls) {
        final Constructor<?> c = cls.getDeclaredConstructors()[0];
        c.setAccessible(true);
        try {
            final Object n = c.newInstance((Object[]) null);
        } catch (Exception ex) {
            throw new RuntimeException(ex);
        }
    }

    public static void setUsernamePassword(String username, String password) {
        SecurityContextHolder.getContext().setAuthentication(
                new UsernamePasswordAuthenticationToken(username, password));
    }

    public static String getCurrentUsername() {
        return SecurityContextHolder.getContext().getAuthentication().getName();
    }

    public static void logout() {
        SecurityContextHolder.getContext().setAuthentication(null);
    }

    public static void login(AllocatorOrDatacentre user) {
        if (user == null) {
            logout();
        } else {
            setUsernamePassword(user.getSymbol(), user.getPassword());
        }
    }

    public static void persist(Object... objects) {
        for (Object object : objects) {
            if (object instanceof AllocatorOrDatacentre)
                ((AllocatorOrDatacentre) object).persist();
            else
                throw new IllegalArgumentException("unknown type");
        }
    }

    public static Allocator createAllocator(String symbol) {
        Allocator allocator = new Allocator();
        allocator.setSymbol(symbol);
        allocator.setPassword("12345678");
        allocator.setContactEmail("dummy@example.com");
        allocator.setContactName("example contact");
        allocator.setDoiQuotaAllowed(-1);
        allocator.setDoiQuotaUsed(0);
        allocator.setIsActive(true);
        allocator.setName("example name");
        allocator.setRoleName("ROLE_ALLOCATOR");
        return allocator;
    }

    public static Allocator createAdmin(String symbol) {
        Allocator admin = createAllocator(symbol);
        admin.setRoleName("ROLE_ADMIN");
        return admin;
    }

    public static Allocator createDev(String symbol) {
        Allocator dev = createAllocator(symbol);
        dev.setRoleName("ROLE_DEV");
        return dev;
    }

    public static Datacentre createDatacentre(String symbol, Allocator allocator) {
        Datacentre datacentre = new Datacentre();
        datacentre.setSymbol(symbol);
        datacentre.setAllocator(allocator);
        datacentre.setContactEmail("dummy@example.com");
        datacentre.setContactName("example contact");
        datacentre.setDoiQuotaAllowed(-1);
        datacentre.setDoiQuotaUsed(0);
        datacentre.setDomains("example.com");
        datacentre.setIsActive(true);
        datacentre.setName("example name");
        datacentre.setRoleName("ROLE_DATACENTRE");
        return datacentre;
    }

    public static Dataset createDataset(String doi, Datacentre datacentre) {
        Dataset dataset = new Dataset();
        dataset.setDoi(doi);
        dataset.setDatacentre(datacentre);
        return dataset;
    }

    public static Prefix createPrefix(String prefix) {
        Prefix prefixObj = new Prefix();
        prefixObj.setPrefix(prefix);
        return prefixObj;
    }

    public static Set<Prefix> createPrefixes(String... prefixes) {
        Set<Prefix> prefixSet = new HashSet<Prefix>();
        if (prefixes != null) {
            for (String prefix : prefixes) {
                prefixSet.add(createPrefix(prefix));
            }
        }
        return prefixSet;
    }
    
    public static byte[] getTestMetadata() throws IOException {
        return getTestMetadata20();
    }

    public static byte[] getTestMetadata20() throws IOException {
        return getTestMetadata("datacite-metadata-sample-v2.0.xml");
    }
    
    public static byte[] getTestMetadata21() throws IOException {
        return getTestMetadata("datacite-metadata-sample-v2.1.xml");
    }
    
    private static byte[] getTestMetadata(String filename) throws IOException {
        InputStream in = TestUtils.class.getClassLoader().getResourceAsStream(filename);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            byte[] buffer = new byte[1024];
            int n;
            while ((n = in.read(buffer)) != -1) {
                out.write(buffer, 0, n);
            }

            return out.toByteArray();
        } finally {
            in.close();
            out.close();
        }
    }
}

@@ -202,24 +202,64 @@
 .util.Set;%0A%0A
+import org.apache.commons.io.FileUtils;%0A
 import org.d
@@ -464,16 +464,115 @@
 Prefix;%0A
+import org.springframework.core.io.ClassPathResource;%0Aimport org.springframework.core.io.Resource;%0A
 import o
@@ -4439,35 +4439,16 @@
 tadata()
- throws IOException
  %7B%0A     
@@ -4529,35 +4529,16 @@
 data20()
- throws IOException
  %7B%0A     
@@ -4656,35 +4656,16 @@
 data21()
- throws IOException
  %7B%0A     
@@ -4802,470 +4802,229 @@
 me) 
-throws IOException %7B%0A        InputStream in = TestUtils.class.getClassLoader().getResourceAsStream(filename);%0A        ByteArrayOutputStream out = new ByteArrayOutputStream();%0A        try %7B%0A            byte%5B%5D buffer = new byte%5B1024%5D;%0A            int n;%0A            while ((n = in.read(buffer)) != -1) %7B%0A                out.write(buffer, 0, n);%0A            %7D%0A%0A            return out.toByteArray();%0A        %7D finally %7B%0A            in.close();%0A            out.close(
+%7B%0A        Resource resource = new ClassPathResource(filename);%0A        try %7B%0A            return FileUtils.readFileToByteArray(resource.getFile());%0A        %7D catch (IOException e) %7B%0A            throw new RuntimeException(e
 );%0A 

simplify TestUtils