package dk.statsbiblioteket.medieplatform.autonomous;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import java.io.StringWriter;
import java.util.Arrays;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

/**
 * This class collects the result of a run of a component.
 */
public class ResultCollector {

    private Result resultStructure;

    public ResultCollector(String tool,
                           String version) {
        resultStructure = new ObjectFactory().createResult();
        setSuccess(true);
        resultStructure.setFailures(new Failures());
        resultStructure.setTool(tool);
        resultStructure.setVersion(version);
        setTimestamp(new Date());
    }

    /**
     * Get the success value of the execution
     *
     * @return the success
     */
    public boolean isSuccess() {
        return "Success".equals(resultStructure.getOutcome());
    }

    /**
     * Set the success Value of the execution
     *
     * @param success the sucesss
     */
    private void setSuccess(boolean success) {
        resultStructure.setOutcome(success ? "Success" : "Failure");
    }

    /**
     * Add a specific failure to the result collector. All these parameters must be non-null and non-empty
     *
     * @param reference   the reference to the file/object that caused the failure
     * @param type        the type of failure
     * @param component   the component that failed
     * @param description Description of the failure.
     */
    public void addFailure(String reference,
                           String type,
                           String component,
                           String description) {
        addFailure(reference, type, component, description, new String[]{});
    }

    /**
     * Add a specific failure to the result collector. All these parameters must be non-null and non-empty
     *
     * @param reference   the reference to the file/object that caused the failure
     * @param type        the type of failure
     * @param component   the component that failed
     * @param description Description of the failure.
     * @param details     additional details, can be null
     */
    public void addFailure(String reference,
                           String type,
                           String component,
                           String description,
                           String... details) {
        List<Failure> list = resultStructure.getFailures().getFailure();
        Failure failure = new Failure();
        failure.setFilereference(reference);
        failure.setType(type);
        failure.setComponent(component);
        failure.setDescription(description);
        if (details != null) {
            Details xmlDetails = new Details();
            xmlDetails.getContent().addAll(Arrays.asList(details));
        }
        list.add(failure);
        setSuccess(false);
    }

    /**
     * Return the report as xml
     */
    public String toReport() {
        try {
            JAXBContext context = JAXBContext.newInstance(ObjectFactory.class);
            Marshaller marshaller = context.createMarshaller();
            marshaller.setProperty("jaxb.fragment", Boolean.TRUE);
            StringWriter writer = new StringWriter();
            marshaller.marshal(resultStructure, writer);
            return writer.toString();
        } catch (JAXBException e) {
            return null;
        }
    }

    /**
     * The timestamp of the event
     *
     * @return
     */
    public Date getTimestamp() {
        return resultStructure.getDate().toGregorianCalendar().getTime();
    }

    /**
     * Timestamp the event that this is the result of
     *
     * @param timestamp
     */
    public void setTimestamp(Date timestamp) {
        resultStructure.setDate(format(timestamp));

    }

    private XMLGregorianCalendar format(Date date) {
        GregorianCalendar c = new GregorianCalendar();
        c.setTime(date);
        XMLGregorianCalendar date2 = null;
        try {
            date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
        } catch (DatatypeConfigurationException e) {
            throw new Error(e);
        }
        return date2;
    }
}

@@ -354,19 +354,77 @@
 il.Array
+List;%0Aimport java.util.Arrays;%0Aimport java.util.Collection
 s;%0A
-
 import j
@@ -501,19 +501,16 @@
 st;%0A%0A/**
-%0A *
  This cl
@@ -557,17 +557,16 @@
 mponent.
-%0A
  */%0Apubl
@@ -3191,16 +3191,1222 @@
 %0A     * 
+Merge the failures from this ResultCollector into the given result collector%0A     * @param that the result collector to merge into%0A     * @return that%0A     */%0A    public ResultCollector mergeInto(ResultCollector that) %7B%0A        for (Failure failure : getFailures()) %7B%0A            ArrayList%3CString%3E details = new ArrayList%3C%3E();%0A            for (Object content : failure.getDetails().getContent()) %7B%0A                details.add(content.toString());%0A            %7D%0A            that.addFailure(failure.getFilereference(),%0A                            failure.getType(),%0A                            failure.getComponent(),%0A                            failure.getDescription(),%0A                            details.toArray(new String%5Bdetails.size()%5D));%0A            if (that.getTimestamp().before(this.getTimestamp()))%7B%0A                that.setTimestamp(this.getTimestamp());%0A            %7D%0A        %7D%0A        return that;%0A    %7D%0A%0A    /**%0A     * Get the list of failures. This method is only meant to be used for merging purposes%0A     *%0A     * @return the failures%0A     */%0A    private List%3CFailure%3E getFailures() %7B%0A        return Collections.unmodifiableList(resultStructure.getFailures().getFailure());%0A    %7D%0A%0A    /** 
 Return t
@@ -4421,21 +4421,16 @@
 t as xml
-%0A    
  */%0A    

Support for merging of resultcollectors