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 */ 006 007package org.fcrepo.persistence.ocfl.impl; 008 009import org.fcrepo.kernel.api.operations.CreateVersionResourceOperation; 010import org.fcrepo.kernel.api.operations.ResourceOperation; 011import org.fcrepo.kernel.api.operations.ResourceOperationType; 012import org.fcrepo.persistence.api.exceptions.PersistentItemConflictException; 013import org.fcrepo.persistence.api.exceptions.PersistentStorageException; 014import org.fcrepo.persistence.common.ResourceHeaderUtils; 015import org.fcrepo.persistence.ocfl.api.FedoraToOcflObjectIndex; 016import org.fcrepo.storage.ocfl.CommitType; 017import org.slf4j.Logger; 018import org.slf4j.LoggerFactory; 019 020/** 021 * Persister for creating a new OCFL version of a resource. The new version is not created until the session 022 * is committed. 023 * 024 * @author pwinckles 025 */ 026public class CreateVersionPersister extends AbstractPersister { 027 028 private static final Logger LOG = LoggerFactory.getLogger(CreateVersionPersister.class); 029 030 protected CreateVersionPersister(final FedoraToOcflObjectIndex index) { 031 super(CreateVersionResourceOperation.class, ResourceOperationType.UPDATE, index); 032 } 033 034 @Override 035 public void persist(final OcflPersistentStorageSession session, final ResourceOperation operation) 036 throws PersistentStorageException { 037 038 final var resourceId = operation.getResourceId(); 039 LOG.debug("creating new version of <{}> in session <{}>", resourceId, session); 040 041 final var archivalGroupId = findArchivalGroupInAncestry(resourceId, session); 042 043 if (archivalGroupId.isPresent() && !archivalGroupId.get().equals(resourceId)) { 044 throw new PersistentItemConflictException( 045 String.format("Resource <%s> is contained in Archival Group <%s> and cannot be versioned directly." 046 + " Version the Archival Group instead.", resourceId, archivalGroupId)); 047 } 048 049 final var ocflMapping = getMapping(operation.getTransaction(), resourceId); 050 final var ocflObjectSession = session.findOrCreateSession(ocflMapping.getOcflObjectId()); 051 052 // Touching the last modified date is necessary so that resource that do not have any outstanding changes are 053 // still versioned 054 final var headers = new ResourceHeadersAdapter(ocflObjectSession.readHeaders(resourceId.getResourceId())) 055 .asKernelHeaders(); 056 ResourceHeaderUtils.touchMementoCreateHeaders(headers); 057 058 ocflObjectSession.writeHeaders(new ResourceHeadersAdapter(headers).asStorageHeaders()); 059 // The version is not actually created until the session is committed 060 ocflObjectSession.commitType(CommitType.NEW_VERSION); 061 } 062 063}