001/*
002 * The contents of this file are subject to the license and copyright
003 * detailed in the LICENSE and NOTICE files at the root of the source
004 * tree.
005 */
006package org.fcrepo.persistence.ocfl.impl;
007
008import org.fcrepo.kernel.api.identifiers.FedoraId;
009import org.fcrepo.kernel.api.operations.OverwriteTombstoneOperation;
010import org.fcrepo.kernel.api.operations.RdfSourceOperation;
011import org.fcrepo.kernel.api.operations.ResourceOperation;
012import org.fcrepo.kernel.api.operations.ResourceOperationType;
013import org.fcrepo.persistence.api.exceptions.PersistentItemConflictException;
014import org.fcrepo.persistence.api.exceptions.PersistentItemNotFoundException;
015import org.fcrepo.persistence.api.exceptions.PersistentStorageException;
016import org.fcrepo.persistence.ocfl.api.FedoraToOcflObjectIndex;
017import org.fcrepo.storage.ocfl.OcflObjectSession;
018import org.slf4j.Logger;
019import org.slf4j.LoggerFactory;
020
021/**
022 * Persistence for overwriting tombstones of an RDFSource
023 *
024 * @author mikejritter
025 */
026public class OverwriteRdfTombstonePersister extends AbstractRdfSourcePersister {
027
028    private static final Logger log = LoggerFactory.getLogger(OverwriteRdfTombstonePersister.class);
029
030    /**
031     * Constructor
032     *
033     * @param index the FedoraToOCFLObjectIndex
034     */
035    protected OverwriteRdfTombstonePersister(final FedoraToOcflObjectIndex index) {
036        super(RdfSourceOperation.class, ResourceOperationType.OVERWRITE_TOMBSTONE, index);
037    }
038
039    @Override
040    public void persist(final OcflPersistentStorageSession session, final ResourceOperation operation)
041        throws PersistentStorageException {
042        final var resourceId = operation.getResourceId();
043        log.debug("persisting {} to {}", resourceId, session);
044
045        final OverwriteTombstoneOperation overwriteTombstoneOp = ((OverwriteTombstoneOperation) operation);
046        final boolean archivalGroup = overwriteTombstoneOp.isArchivalGroup();
047
048        final var headers = session.getHeaders(resourceId, null);
049        if (headers == null) {
050            throw new PersistentItemNotFoundException("Resource does not exist");
051        } else if (!headers.isDeleted()) {
052            throw new PersistentStorageException("Cannot overwrite tombstone of non-deleted resource");
053        }
054
055
056        final FedoraId rootObjectId;
057        // Check to make sure the interaction model hasn't changed from an ArchivalGroup or Atomic Resource
058        if (archivalGroup) {
059            if (!headers.isArchivalGroup()) {
060                throw new PersistentItemConflictException("Changing from an Atomic Resource to an ArchivalGroup is " +
061                                                          "not permitted");
062            }
063
064            rootObjectId = resourceId;
065        } else if (headers.isArchivalGroup()) {
066            throw new PersistentItemConflictException("Changing from an ArchivalGroup to an Atomic Resource is not " +
067                                                      "permitted");
068        } else {
069            rootObjectId = headers.getArchivalGroupId() != null ? headers.getArchivalGroupId() : resourceId.asBaseId();
070        }
071
072        final String ocflObjectId = mapToOcflId(operation.getTransaction(), rootObjectId);
073        final OcflObjectSession ocflObjectSession = session.findOrCreateSession(ocflObjectId);
074        persistRDF(ocflObjectSession, operation, rootObjectId.asBaseId(), headers.getArchivalGroupId() != null);
075        ocflIndex.addMapping(operation.getTransaction(), resourceId.asResourceId(), rootObjectId.asBaseId(),
076                             ocflObjectId);
077    }
078}