001
002/*
003 * Licensed to DuraSpace under one or more contributor license agreements.
004 * See the NOTICE file distributed with this work for additional information
005 * regarding copyright ownership.
006 *
007 * DuraSpace licenses this file to you under the Apache License,
008 * Version 2.0 (the "License"); you may not use this file except in
009 * compliance with the License.  You may obtain a copy of the License at
010 *
011 *     http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing, software
014 * distributed under the License is distributed on an "AS IS" BASIS,
015 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
016 * See the License for the specific language governing permissions and
017 * limitations under the License.
018 */
019package org.fcrepo.kernel.impl.services;
020
021import org.apache.jena.rdf.model.Model;
022import org.fcrepo.kernel.api.RdfLexicon;
023import org.fcrepo.kernel.api.Transaction;
024import org.fcrepo.kernel.api.exception.MalformedRdfException;
025import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
026import org.fcrepo.kernel.api.identifiers.FedoraId;
027import org.fcrepo.kernel.api.operations.RdfSourceOperationFactory;
028import org.fcrepo.kernel.api.operations.ResourceOperation;
029import org.fcrepo.kernel.api.services.ReplacePropertiesService;
030import org.fcrepo.persistence.api.PersistentStorageSession;
031import org.fcrepo.persistence.api.PersistentStorageSessionManager;
032import org.fcrepo.persistence.api.exceptions.PersistentStorageException;
033import org.springframework.stereotype.Component;
034
035import javax.inject.Inject;
036
037import static org.fcrepo.kernel.api.rdf.DefaultRdfStream.fromModel;
038
039/**
040 * This class mediates update operations between the kernel and persistent storage layers
041 * @author bseeger
042 */
043@Component
044public class ReplacePropertiesServiceImpl extends AbstractService implements ReplacePropertiesService {
045
046    @Inject
047    private PersistentStorageSessionManager psManager;
048
049    @Inject
050    private RdfSourceOperationFactory factory;
051
052    @Override
053    public void perform(final Transaction tx,
054                        final String userPrincipal,
055                        final FedoraId fedoraId,
056                        final Model inputModel) throws MalformedRdfException {
057        final var txId = tx.getId();
058        try {
059            final PersistentStorageSession pSession = this.psManager.getSession(txId);
060
061            final var headers = pSession.getHeaders(fedoraId, null);
062            final var interactionModel = headers.getInteractionModel();
063
064            ensureValidDirectContainer(fedoraId, interactionModel, inputModel);
065            ensureValidACLAuthorization(inputModel);
066
067            final ResourceOperation updateOp = factory.updateBuilder(fedoraId)
068                .relaxedProperties(inputModel)
069                .userPrincipal(userPrincipal)
070                .triples(fromModel(inputModel.createResource(fedoraId.getFullId()).asNode(), inputModel))
071                .build();
072
073            lockArchivalGroupResource(tx, pSession, fedoraId);
074            tx.lockResource(fedoraId);
075            if (RdfLexicon.FEDORA_NON_RDF_SOURCE_DESCRIPTION_URI.equals(interactionModel)) {
076                tx.lockResource(fedoraId.asBaseId());
077            }
078
079            pSession.persist(updateOp);
080            updateReferences(txId, fedoraId, userPrincipal, inputModel);
081            membershipService.resourceModified(txId, fedoraId);
082            recordEvent(txId, fedoraId, updateOp);
083        } catch (final PersistentStorageException ex) {
084            throw new RepositoryRuntimeException(String.format("failed to replace resource %s",
085                  fedoraId), ex);
086        }
087    }
088}