<commit_before>package dk.statsbiblioteket.medieplatform.autonomous;

import dk.statsbiblioteket.doms.central.connectors.BackendInvalidCredsException;
import dk.statsbiblioteket.doms.central.connectors.BackendInvalidResourceException;
import dk.statsbiblioteket.doms.central.connectors.BackendMethodFailedException;
import dk.statsbiblioteket.doms.central.connectors.EnhancedFedora;
import dk.statsbiblioteket.doms.central.connectors.fedora.pidGenerator.PIDGeneratorException;
import dk.statsbiblioteket.doms.central.connectors.fedora.structures.FedoraRelation;
import dk.statsbiblioteket.doms.central.connectors.fedora.templates.ObjectIsWrongTypeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBException;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * Access to DOMS batch and event storageusing the Central Webservice library to communicate with DOMS.
 * Implements the {@link EventStorer} interface.
 */
public class DomsEventStorage implements EventStorer {

    private static Logger log = LoggerFactory.getLogger(DomsEventStorage.class);

    private final EnhancedFedora fedora;
    private final IDFormatter idFormatter;
    private final String batchTemplate;
    private final String roundTripTemplate;
    private final String hasPart_relation;
    private final String eventsDatastream;
    private final PremisManipulatorFactory premisFactory;
    private String createBatchRoundTripComment = "Creating batch round trip";
    private String addEventToBatchComment = "Adding event to natch round trip";

    DomsEventStorage(EnhancedFedora fedora, IDFormatter idFormatter, String type, String batchTemplate,
                     String roundTripTemplate, String hasPart_relation, String eventsDatastream) throws JAXBException {
        this.fedora = fedora;
        this.idFormatter = idFormatter;
        this.batchTemplate = batchTemplate;
        this.roundTripTemplate = roundTripTemplate;
        this.hasPart_relation = hasPart_relation;
        this.eventsDatastream = eventsDatastream;
        premisFactory = new PremisManipulatorFactory(idFormatter, type);
    }

    @Override
    public Date addEventToBatch(String batchId, int roundTripNumber, String agent, Date timestamp, String details,
                                String eventType, boolean outcome) throws CommunicationException {
        String roundTripObjectPid = createBatchRoundTrip(batchId, roundTripNumber);

        try {
            PremisManipulator premisObject;
            try {
                String premisPreBlob = fedora.getXMLDatastreamContents(roundTripObjectPid, eventsDatastream, null);

                premisObject = premisFactory.createFromBlob(new ByteArrayInputStream(premisPreBlob.getBytes()));
            } catch (BackendInvalidResourceException e) {
                //okay, no EVENTS datastream
                premisObject = premisFactory.createInitialPremisBlob(batchId, roundTripNumber);
            }
            premisObject = premisObject.addEvent(agent, timestamp, details, eventType, outcome);
            try {
                return fedora.modifyDatastreamByValue(
                        roundTripObjectPid,
                        eventsDatastream,
                        null,
                        null,
                        premisObject.toXML().getBytes(),
                        null,
                        "text/xml",
                        addEventToBatchComment,
                        null);
            } catch (BackendInvalidResourceException e1) {
                //But I just created the object, it must be there
                throw new CommunicationException(e1);
            }
        } catch (BackendMethodFailedException | BackendInvalidCredsException | JAXBException e) {
            throw new CommunicationException(e);
        }
    }

    /**
     * Create a batch and round trip object, without adding any events
     *
     * @param batchId         the batch id
     * @param roundTripNumber the round trip number
     *
     * @return the pid of the doms object corresponding to the round trip
     * @throws CommunicationException if communication with doms failed
     */
    public String createBatchRoundTrip(String batchId, int roundTripNumber) throws CommunicationException {
        String id = idFormatter.formatFullID(batchId, roundTripNumber);
        try {
            try {
                //find the roundTrip Object
                return getRoundTripID(batchId, roundTripNumber);
            } catch (BackendInvalidResourceException e) {
                //no roundTripObject, so sad
                //but alas, we can continue
            }

            //find the batch object
            String batchObject;

            List<String> founds = fedora.findObjectFromDCIdentifier(idFormatter.formatBatchID(batchId));
            if (founds.size() > 0) {
                batchObject = founds.get(0);
            } else {
                //no batch object either, more sad
                //create it, then
                batchObject = fedora.cloneTemplate(
                        batchTemplate, Arrays.asList(idFormatter.formatBatchID(batchId)), createBatchRoundTripComment);
            }
            String roundTripObject;

            roundTripObject = fedora.cloneTemplate(roundTripTemplate, Arrays.asList(id), createBatchRoundTripComment);

            //connect batch object to round trip object
            fedora.addRelation(
                    batchObject,
                    toFedoraID(batchObject),
                    hasPart_relation,
                    toFedoraID(roundTripObject),
                    false,
                    createBatchRoundTripComment);

            //create the initial EVENTS datastream

            String premisBlob = premisFactory.createInitialPremisBlob(batchId, roundTripNumber).toXML();
            fedora.modifyDatastreamByValue(
                    roundTripObject, eventsDatastream, null,null,premisBlob.getBytes(), null, "text/xml",createBatchRoundTripComment,null);


            return roundTripObject;
        } catch (BackendMethodFailedException | BackendInvalidCredsException | PIDGeneratorException |
                BackendInvalidResourceException | ObjectIsWrongTypeException | JAXBException e) {
            throw new CommunicationException(e);
        }


    }

    public Batch getBatch(String batchId, Integer roundTripNumber) throws CommunicationException, NotFoundException {
        String roundTripID;
        try {
            roundTripID = getRoundTripID(batchId, roundTripNumber);
            return getBatch(roundTripID);
        } catch (BackendInvalidResourceException e) {
            throw new NotFoundException(e);<commit_msg>Do not NPE on null roundtrip number<commit_after>package dk.statsbiblioteket.medieplatform.autonomous;

import dk.statsbiblioteket.doms.central.connectors.BackendInvalidCredsException;
import dk.statsbiblioteket.doms.central.connectors.BackendInvalidResourceException;
import dk.statsbiblioteket.doms.central.connectors.BackendMethodFailedException;
import dk.statsbiblioteket.doms.central.connectors.EnhancedFedora;
import dk.statsbiblioteket.doms.central.connectors.fedora.pidGenerator.PIDGeneratorException;
import dk.statsbiblioteket.doms.central.connectors.fedora.structures.FedoraRelation;
import dk.statsbiblioteket.doms.central.connectors.fedora.templates.ObjectIsWrongTypeException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.xml.bind.JAXBException;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.util.*;

/**
 * Access to DOMS batch and event storageusing the Central Webservice library to communicate with DOMS.
 * Implements the {@link EventStorer} interface.
 */
public class DomsEventStorage implements EventStorer {

    private static Logger log = LoggerFactory.getLogger(DomsEventStorage.class);

    private final EnhancedFedora fedora;
    private final IDFormatter idFormatter;
    private final String batchTemplate;
    private final String roundTripTemplate;
    private final String hasPart_relation;
    private final String eventsDatastream;
    private final PremisManipulatorFactory premisFactory;
    private String createBatchRoundTripComment = "Creating batch round trip";
    private String addEventToBatchComment = "Adding event to natch round trip";

    DomsEventStorage(EnhancedFedora fedora, IDFormatter idFormatter, String type, String batchTemplate,
                     String roundTripTemplate, String hasPart_relation, String eventsDatastream) throws JAXBException {
        this.fedora = fedora;
        this.idFormatter = idFormatter;
        this.batchTemplate = batchTemplate;
        this.roundTripTemplate = roundTripTemplate;
        this.hasPart_relation = hasPart_relation;
        this.eventsDatastream = eventsDatastream;
        premisFactory = new PremisManipulatorFactory(idFormatter, type);
    }

    @Override
    public Date addEventToBatch(String batchId, int roundTripNumber, String agent, Date timestamp, String details,
                                String eventType, boolean outcome) throws CommunicationException {
        String roundTripObjectPid = createBatchRoundTrip(batchId, roundTripNumber);

        try {
            PremisManipulator premisObject;
            try {
                String premisPreBlob = fedora.getXMLDatastreamContents(roundTripObjectPid, eventsDatastream, null);

                premisObject = premisFactory.createFromBlob(new ByteArrayInputStream(premisPreBlob.getBytes()));
            } catch (BackendInvalidResourceException e) {
                //okay, no EVENTS datastream
                premisObject = premisFactory.createInitialPremisBlob(batchId, roundTripNumber);
            }
            premisObject = premisObject.addEvent(agent, timestamp, details, eventType, outcome);
            try {
                return fedora.modifyDatastreamByValue(
                        roundTripObjectPid,
                        eventsDatastream,
                        null,
                        null,
                        premisObject.toXML().getBytes(),
                        null,
                        "text/xml",
                        addEventToBatchComment,
                        null);
            } catch (BackendInvalidResourceException e1) {
                //But I just created the object, it must be there
                throw new CommunicationException(e1);
            }
        } catch (BackendMethodFailedException | BackendInvalidCredsException | JAXBException e) {
            throw new CommunicationException(e);
        }
    }

    /**
     * Create a batch and round trip object, without adding any events
     *
     * @param batchId         the batch id
     * @param roundTripNumber the round trip number
     *
     * @return the pid of the doms object corresponding to the round trip
     * @throws CommunicationException if communication with doms failed
     */
    public String createBatchRoundTrip(String batchId, int roundTripNumber) throws CommunicationException {
        String id = idFormatter.formatFullID(batchId, roundTripNumber);
        try {
            try {
                //find the roundTrip Object
                return getRoundTripID(batchId, roundTripNumber);
            } catch (BackendInvalidResourceException e) {
                //no roundTripObject, so sad
                //but alas, we can continue
            }

            //find the batch object
            String batchObject;

            List<String> founds = fedora.findObjectFromDCIdentifier(idFormatter.formatBatchID(batchId));
            if (founds.size() > 0) {
                batchObject = founds.get(0);
            } else {
                //no batch object either, more sad
                //create it, then
                batchObject = fedora.cloneTemplate(
                        batchTemplate, Arrays.asList(idFormatter.formatBatchID(batchId)), createBatchRoundTripComment);
            }
            String roundTripObject;

            roundTripObject = fedora.cloneTemplate(roundTripTemplate, Arrays.asList(id), createBatchRoundTripComment);

            //connect batch object to round trip object
            fedora.addRelation(
                    batchObject,
                    toFedoraID(batchObject),
                    hasPart_relation,
                    toFedoraID(roundTripObject),
                    false,
                    createBatchRoundTripComment);

            //create the initial EVENTS datastream

            String premisBlob = premisFactory.createInitialPremisBlob(batchId, roundTripNumber).toXML();
            fedora.modifyDatastreamByValue(
                    roundTripObject, eventsDatastream, null,null,premisBlob.getBytes(), null, "text/xml",createBatchRoundTripComment,null);


            return roundTripObject;
        } catch (BackendMethodFailedException | BackendInvalidCredsException | PIDGeneratorException |
                BackendInvalidResourceException | ObjectIsWrongTypeException | JAXBException e) {
            throw new CommunicationException(e);
        }


    }

    public Batch getBatch(String batchId, Integer roundTripNumber) throws CommunicationException, NotFoundException {
        String roundTripID;
        if (roundTripNumber == null) {
            roundTripNumber = 0;
        }
        try {
            roundTripID = getRoundTripID(batchId, roundTripNumber);
            return getBatch(roundTripID);
        } catch (BackendInvalidResourceException e) {
            throw new NotFoundException(e);
{'fraction_non_alphanumeric': 0.06327634078620488, 'fraction_numerical': 0.0009498757854742073, 'mean_word_length': 2.507688364941056, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4561109', 'n_tokens_mistral': 3549, 'n_tokens_neox': 3384, 'n_words': 800}