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                    fedoraPropsConfig.getServerManagedPropsMode())
069                .relaxedProperties(inputModel)
070                .userPrincipal(userPrincipal)
071                .triples(fromModel(inputModel.createResource(fedoraId.getFullId()).asNode(), inputModel))
072                .build();
073
074            lockArchivalGroupResource(tx, pSession, fedoraId);
075            tx.lockResource(fedoraId);
076            if (RdfLexicon.FEDORA_NON_RDF_SOURCE_DESCRIPTION_URI.equals(interactionModel)) {
077                tx.lockResource(fedoraId.asBaseId());
078            }
079
080            pSession.persist(updateOp);
081            updateReferences(txId, fedoraId, userPrincipal, inputModel);
082            membershipService.resourceModified(txId, fedoraId);
083            recordEvent(txId, fedoraId, updateOp);
084        } catch (final PersistentStorageException ex) {
085            throw new RepositoryRuntimeException(String.format("failed to replace resource %s",
086                  fedoraId), ex);
087        }
088    }
089}