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;
022
023import org.fcrepo.kernel.api.RdfLexicon;
024import org.fcrepo.kernel.api.Transaction;
025import org.fcrepo.kernel.api.exception.MalformedRdfException;
026import org.fcrepo.kernel.api.exception.RepositoryRuntimeException;
027import org.fcrepo.kernel.api.identifiers.FedoraId;
028import org.fcrepo.kernel.api.operations.RdfSourceOperationFactory;
029import org.fcrepo.kernel.api.operations.ResourceOperation;
030import org.fcrepo.kernel.api.services.ReplacePropertiesService;
031import org.fcrepo.persistence.api.PersistentStorageSession;
032import org.fcrepo.persistence.api.PersistentStorageSessionManager;
033import org.fcrepo.persistence.api.exceptions.PersistentStorageException;
034import org.springframework.stereotype.Component;
035
036import javax.inject.Inject;
037
038import static org.fcrepo.kernel.api.rdf.DefaultRdfStream.fromModel;
039
040/**
041 * This class mediates update operations between the kernel and persistent storage layers
042 * @author bseeger
043 */
044@Component
045public class ReplacePropertiesServiceImpl extends AbstractService implements ReplacePropertiesService {
046
047    @Inject
048    private PersistentStorageSessionManager psManager;
049
050    @Inject
051    private RdfSourceOperationFactory factory;
052
053    @Override
054    public void perform(final Transaction tx,
055                        final String userPrincipal,
056                        final FedoraId fedoraId,
057                        final Model inputModel) throws MalformedRdfException {
058        try {
059            final PersistentStorageSession pSession = this.psManager.getSession(tx);
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(tx, 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(tx, fedoraId, userPrincipal, inputModel);
082            membershipService.resourceModified(tx, fedoraId);
083            searchIndex.addUpdateIndex(tx, pSession.getHeaders(fedoraId, null));
084            recordEvent(tx, fedoraId, updateOp);
085        } catch (final PersistentStorageException ex) {
086            throw new RepositoryRuntimeException(String.format("failed to replace resource %s",
087                    fedoraId), ex);
088        }
089    }
090}