001/*
002 * Licensed to DuraSpace under one or more contributor license agreements.
003 * See the NOTICE file distributed with this work for additional information
004 * regarding copyright ownership.
005 *
006 * DuraSpace licenses this file to you under the Apache License,
007 * Version 2.0 (the "License"); you may not use this file except in
008 * compliance with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.fcrepo.kernel.impl.services;
019
020import static org.apache.jena.vocabulary.DC_11.title;
021import static org.junit.Assert.assertEquals;
022import static org.junit.Assert.assertTrue;
023import static org.mockito.ArgumentMatchers.any;
024import static org.mockito.ArgumentMatchers.nullable;
025import static org.mockito.Mockito.verify;
026import static org.mockito.Mockito.when;
027import static org.springframework.test.util.ReflectionTestUtils.setField;
028
029import java.time.Instant;
030
031import org.fcrepo.config.FedoraPropsConfig;
032import org.fcrepo.config.ServerManagedPropsMode;
033import org.fcrepo.kernel.api.RdfCollectors;
034import org.fcrepo.kernel.api.RdfLexicon;
035import org.fcrepo.kernel.api.RdfStream;
036import org.fcrepo.kernel.api.Transaction;
037import org.fcrepo.kernel.api.identifiers.FedoraId;
038import org.fcrepo.kernel.api.models.ResourceHeaders;
039import org.fcrepo.kernel.api.observer.EventAccumulator;
040import org.fcrepo.kernel.api.operations.RdfSourceOperationFactory;
041import org.fcrepo.kernel.api.services.MembershipService;
042import org.fcrepo.kernel.api.services.ReferenceService;
043import org.fcrepo.kernel.impl.operations.RdfSourceOperationFactoryImpl;
044import org.fcrepo.kernel.impl.operations.UpdateRdfSourceOperation;
045import org.fcrepo.persistence.api.PersistentStorageSession;
046import org.fcrepo.persistence.api.PersistentStorageSessionManager;
047
048import org.apache.commons.io.IOUtils;
049import org.apache.jena.rdf.model.Model;
050import org.apache.jena.rdf.model.ModelFactory;
051import org.apache.jena.rdf.model.ResourceFactory;
052import org.apache.jena.riot.Lang;
053import org.apache.jena.riot.RDFDataMgr;
054import org.fcrepo.search.api.SearchIndex;
055import org.junit.Before;
056import org.junit.Test;
057import org.junit.runner.RunWith;
058import org.mockito.ArgumentCaptor;
059import org.mockito.Captor;
060import org.mockito.InjectMocks;
061import org.mockito.Mock;
062import org.mockito.junit.MockitoJUnitRunner;
063
064/**
065 * DeleteResourceServiceTest
066 *
067 * @author bseeger
068 */
069@RunWith(MockitoJUnitRunner.Strict.class)
070public class ReplacePropertiesServiceImplTest {
071
072    private static final String USER_PRINCIPAL = "fedoraUser";
073
074    @Mock
075    private Transaction tx;
076
077    @Mock
078    private PersistentStorageSession pSession;
079
080    @Mock
081    private PersistentStorageSessionManager psManager;
082
083    @Mock
084    private EventAccumulator eventAccumulator;
085
086    @Mock
087    private ReferenceService referenceService;
088
089    @Mock
090    private MembershipService membershipService;
091
092    @Mock
093    private SearchIndex searchIndex;
094
095    @Mock
096    private ResourceHeaders headers;
097
098    @InjectMocks
099    private UpdateRdfSourceOperation operation;
100
101    @InjectMocks
102    private ReplacePropertiesServiceImpl service;
103
104    private RdfSourceOperationFactory factory;
105
106    @Captor
107    private ArgumentCaptor<UpdateRdfSourceOperation> operationCaptor;
108
109    private FedoraPropsConfig propsConfig;
110
111    private static final FedoraId FEDORA_ID = FedoraId.create("info:fedora/resource1");
112    private static final String TX_ID = "tx-1234";
113    private static final String RDF =
114            "<" + FEDORA_ID + "> <" + title + "> 'fancy title' .\n" +
115            "<" + FEDORA_ID + "> <" + title + "> 'another fancy title' .";
116
117    @Before
118    public void setup() {
119        propsConfig = new FedoraPropsConfig();
120        factory = new RdfSourceOperationFactoryImpl();
121        setField(service, "factory", factory);
122        setField(service, "eventAccumulator", eventAccumulator);
123        setField(service, "referenceService", referenceService);
124        setField(service, "membershipService", membershipService);
125        setField(service, "searchIndex", searchIndex);
126        setField(service, "fedoraPropsConfig", propsConfig);
127        propsConfig.setServerManagedPropsMode(ServerManagedPropsMode.STRICT);
128        when(psManager.getSession(any(Transaction.class))).thenReturn(pSession);
129        when(pSession.getHeaders(any(FedoraId.class), nullable(Instant.class))).thenReturn(headers);
130    }
131
132    @Test
133    public void testReplaceProperties() throws Exception {
134        final Model model = ModelFactory.createDefaultModel();
135        RDFDataMgr.read(model, IOUtils.toInputStream(RDF, "UTF-8"), Lang.NTRIPLES);
136
137        when(headers.getInteractionModel()).thenReturn(RdfLexicon.RDF_SOURCE.toString());
138
139        service.perform(tx, USER_PRINCIPAL, FEDORA_ID, model);
140        verify(tx).lockResource(FEDORA_ID);
141        verify(pSession).persist(operationCaptor.capture());
142        assertEquals(FEDORA_ID, operationCaptor.getValue().getResourceId());
143        final RdfStream stream = operationCaptor.getValue().getTriples();
144        final Model captureModel = stream.collect(RdfCollectors.toModel());
145
146        assertTrue(captureModel.contains(ResourceFactory.createResource(FEDORA_ID.getResourceId()),
147                ResourceFactory.createProperty(title.getURI()),
148                "another fancy title"));
149        assertTrue(captureModel.contains(ResourceFactory.createResource(FEDORA_ID.getResourceId()),
150                ResourceFactory.createProperty(title.getURI()),
151                "fancy title"));
152    }
153
154    @Test
155    public void lockRelatedResourcesOnBinaryDescInAg() throws Exception {
156        final Model model = ModelFactory.createDefaultModel();
157        RDFDataMgr.read(model, IOUtils.toInputStream(RDF, "UTF-8"), Lang.NTRIPLES);
158
159        final var agId = FedoraId.create("ag");
160        final var binaryId = agId.resolve("bin");
161        final var descId = binaryId.asDescription();
162
163        when(headers.getInteractionModel()).thenReturn(RdfLexicon.FEDORA_NON_RDF_SOURCE_DESCRIPTION_URI);
164        when(headers.getArchivalGroupId()).thenReturn(agId);
165
166        service.perform(tx, USER_PRINCIPAL, descId, model);
167        verify(tx).lockResource(agId);
168        verify(tx).lockResource(binaryId);
169        verify(tx).lockResource(descId);
170        verify(pSession).persist(operationCaptor.capture());
171        assertEquals(descId, operationCaptor.getValue().getResourceId());
172    }
173
174}
175