org.fcrepo.importexport.exporter.ExportVersionsTest.java Source code

Java tutorial

Introduction

Here is the source code for org.fcrepo.importexport.exporter.ExportVersionsTest.java

Source

/*
 * Licensed to DuraSpace under one or more contributor license agreements.
 * See the NOTICE file distributed with this work for additional information
 * regarding copyright ownership.
 *
 * DuraSpace licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file except in
 * compliance with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.fcrepo.importexport.exporter;

import static java.util.Collections.emptyList;
import static org.fcrepo.importexport.common.FcrepoConstants.CONTAINER;
import static org.fcrepo.importexport.common.FcrepoConstants.CONTAINS;
import static org.fcrepo.importexport.common.FcrepoConstants.CREATED_DATE;
import static org.fcrepo.importexport.common.FcrepoConstants.FCR_VERSIONS_PATH;
import static org.fcrepo.importexport.common.FcrepoConstants.HAS_VERSION;
import static org.fcrepo.importexport.common.FcrepoConstants.HAS_VERSION_LABEL;
import static org.fcrepo.importexport.common.FcrepoConstants.NON_RDF_SOURCE;
import static org.fcrepo.importexport.common.FcrepoConstants.RDF_SOURCE;
import static org.fcrepo.importexport.common.FcrepoConstants.REPOSITORY_ROOT;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.isA;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.io.FileUtils;
import org.apache.http.HttpStatus;
import org.apache.jena.rdf.model.Resource;
import org.fcrepo.client.FcrepoClient;
import org.fcrepo.client.FcrepoOperationFailedException;
import org.fcrepo.client.FcrepoResponse;
import org.fcrepo.client.HeadBuilder;
import org.fcrepo.importexport.common.Config;
import org.fcrepo.importexport.test.util.ResponseMocker;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.slf4j.Logger;

/**
 * 
 * @author bbpennel
 *
 */
public class ExportVersionsTest {

    private final String BASE_URI = "http://localhost:8080/rest/";
    private String exportDirectory = "target/export-versions-test";
    private final String basedir = exportDirectory + "/versions";
    private URI rootResource;

    private final String versionCreated = "2017-05-16T17:35:26.608Z";
    private final String versionLabel = "version1";

    @Mock
    private FcrepoClient client;
    @Mock
    private FcrepoClient.FcrepoClientBuilder clientBuilder;
    @Mock
    private FcrepoResponse headResponse;
    @Mock
    private HeadBuilder headBuilder;
    @Mock
    private Config config;
    @Mock
    private Logger auditLog;

    private ExporterWrapper exporter;

    private String[] predicates = new String[] { CONTAINS.toString() };
    private List<URI> containerLinks = Arrays.asList(URI.create(CONTAINER.getURI()));
    private List<URI> binaryLinks = Arrays.asList(URI.create(NON_RDF_SOURCE.getURI()));

    @Before
    public void setUp() throws Exception {
        initMocks(this);

        when(clientBuilder.build()).thenReturn(client);

        final HeadBuilder headBuilder = mock(HeadBuilder.class);
        when(client.head(isA(URI.class))).thenReturn(headBuilder);
        when(headBuilder.disableRedirects()).thenReturn(headBuilder);
        when(headBuilder.perform()).thenReturn(headResponse);
        when(headResponse.getStatusCode()).thenReturn(200);

        when(config.isExport()).thenReturn(true);
        when(config.includeVersions()).thenReturn(true);
        when(config.isIncludeBinaries()).thenReturn(true);
        when(config.getRdfLanguage()).thenReturn("application/ld+json");
        when(config.getRdfExtension()).thenReturn(".jsonld");
        when(config.getPredicates()).thenReturn(predicates);
        when(config.getBaseDirectory()).thenReturn(new File(basedir));
        when(config.getAuditLog()).thenReturn(auditLog);

        exporter = new ExporterWrapper(config, clientBuilder);

        rootResource = new URI("http://localhost:8080/rest");
        mockResponse(rootResource, containerLinks, new ArrayList<>(), createJson(rootResource, REPOSITORY_ROOT));
    }

    @After
    public void tearDown() {
        try {
            FileUtils.deleteDirectory(new File(exportDirectory));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void mockResponse(final URI uri, final List<URI> typeLinks, final List<URI> describedbyLinks,
            final String body) throws FcrepoOperationFailedException {
        ResponseMocker.mockHeadResponse(client, uri, typeLinks, describedbyLinks);

        ResponseMocker.mockGetResponse(client, uri, typeLinks, describedbyLinks, body);
    }

    @Test
    public void testExportVersionsOff() throws Exception {
        final URI resource1 = new URI(BASE_URI + "1");
        final URI resource1Versions = new URI(BASE_URI + "1/fcr:versions");
        final URI resource1Version1 = new URI(BASE_URI + "1/fcr:versions/version1");

        when(config.getResource()).thenReturn(resource1);
        when(config.includeVersions()).thenReturn(false);

        mockResponse(resource1, containerLinks, emptyList(), createJson(resource1));

        // Setup version responses, which should not get invoked
        final String versionsJson = joinJsonArray(
                addVersionJson(new ArrayList<>(), resource1, resource1Version1, versionCreated, versionLabel));
        mockResponse(resource1Versions, emptyList(), emptyList(), versionsJson);
        mockResponse(resource1Version1, containerLinks, emptyList(), createJson(resource1));

        exporter.run();

        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1.jsonld")));
        assertFalse(exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions.jsonld")));
        assertFalse(exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions/version1.jsonld")));
    }

    @Test
    public void testExportVersionsContainers() throws Exception {
        final URI resource1 = new URI(BASE_URI + "1");
        final URI resource2 = new URI(BASE_URI + "1/2");
        final URI resource1Versions = new URI(BASE_URI + "1/fcr:versions");
        final URI resource1Version1 = new URI(BASE_URI + "1/fcr:versions/version1");
        final URI resourceVersionedChild = new URI(BASE_URI + "1/fcr:versions/version1/vChild");
        final URI resource2Versions = new URI(BASE_URI + "1/2/fcr:versions");

        when(config.getResource()).thenReturn(resource1);

        mockResponse(resource1, containerLinks, emptyList(), createJson(resource1, resource2));
        mockResponse(resource2, containerLinks, emptyList(), createJson(resource2));

        final String versionsJson = joinJsonArray(
                addVersionJson(new ArrayList<>(), resource1, resource1Version1, versionCreated, versionLabel));
        mockResponse(resource1Versions, emptyList(), emptyList(), versionsJson);

        mockResponse(resource1Version1, containerLinks, emptyList(), createJson(resource1, resourceVersionedChild));
        mockResponse(resourceVersionedChild, containerLinks, emptyList(), createJson(resourceVersionedChild));

        ResponseMocker.mockGetResponseError(client, resource2Versions, HttpStatus.SC_NOT_FOUND);

        exporter.run();

        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1/2.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions/version1.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions/version1/vChild.jsonld")));
        assertFalse("Child not present in previous version should not appear in version export",
                exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions/version1/2.jsonld")));
    }

    @Test
    public void testExportNonversionedResource() throws Exception {
        final URI resource1 = new URI(BASE_URI + "1");
        final URI resource1Versions = new URI(BASE_URI + "1/fcr:versions");

        when(config.getResource()).thenReturn(resource1);

        mockResponse(resource1, containerLinks, emptyList(), createJson(resource1));

        ResponseMocker.mockGetResponseError(client, resource1Versions, HttpStatus.SC_NOT_FOUND);

        exporter.run();

        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1.jsonld")));
        assertFalse("Versions metadata should not be present for unversioned resource",
                exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions.jsonld")));
        assertFalse("Versions directory should not be present for unversioned resource",
                exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions")));
    }

    @Test
    public void testExportVersionedBinary() throws Exception {
        final URI binaryResc = new URI(BASE_URI + "file1");
        final URI binaryRescMetadata = new URI(BASE_URI + "file1/fcr:metadata");
        final URI binaryRescVersions = new URI(BASE_URI + "file1/fcr:versions");
        final URI binaryRescVersion = new URI(BASE_URI + "file1/fcr:versions/version1");
        final URI binaryRescMetadataVersion = new URI(BASE_URI + "file1/fcr:versions/version1/fcr:metadata");

        mockResponse(binaryResc, binaryLinks, Arrays.asList(binaryRescMetadata), "binary");
        mockResponse(binaryRescVersion, binaryLinks, Arrays.asList(binaryRescMetadataVersion), "old binary");

        final List<URI> descriptionLinks = Arrays.asList(URI.create(RDF_SOURCE.getURI()));
        mockResponse(binaryRescMetadata, descriptionLinks, Collections.emptyList(), createJson(binaryRescMetadata));
        mockResponse(binaryRescMetadataVersion, descriptionLinks, Collections.emptyList(),
                createJson(binaryRescMetadataVersion));

        final String versionsJson = joinJsonArray(
                addVersionJson(new ArrayList<>(), binaryResc, binaryRescVersion, versionCreated, versionLabel));
        mockResponse(binaryRescVersions, emptyList(), emptyList(), versionsJson);

        when(config.getResource()).thenReturn(binaryResc);

        exporter.run();

        assertTrue(exporter.wroteFile(new File(basedir + "/rest/file1.binary")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/file1/fcr%3Ametadata.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/file1/fcr%3Aversions.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/file1/fcr%3Aversions/version1.binary")));
        assertTrue(exporter
                .wroteFile(new File(basedir + "/rest/file1/fcr%3Aversions/version1/fcr%3Ametadata.jsonld")));
    }

    @Test
    public void testExportMultipleVersionsContainers() throws Exception {
        final String version2Label = "version2";
        final String version3Label = "version_original";
        final String version2Created = "2017-05-10T00:00:00.600Z";
        final String version3Created = "2016-12-24T01:00:00.000Z";

        final URI resource = new URI(BASE_URI + "1");
        final URI resourceVersions = new URI(BASE_URI + "1/fcr:versions");
        final URI resourceVersion1 = new URI(BASE_URI + "1/fcr:versions/version1");
        final URI resourceVersion2 = new URI(BASE_URI + "1/fcr:versions/version2");
        final URI resourceVersion3 = new URI(BASE_URI + "1/fcr:versions/version_original");
        final URI resourceVersion2Child = new URI(BASE_URI + "1/fcr:versions/version2/vChild");

        when(config.getResource()).thenReturn(resource);

        mockResponse(resource, containerLinks, emptyList(), createJson(resource));

        // Add all versions to fcr:versions response
        final List<String> versionList = new ArrayList<>();
        addVersionJson(versionList, resource, resourceVersion1, versionCreated, versionLabel);
        addVersionJson(versionList, resource, resourceVersion2, version2Created, version2Label);
        addVersionJson(versionList, resource, resourceVersion3, version3Created, version3Label);
        final String versionsJson = joinJsonArray(versionList);
        mockResponse(resourceVersions, emptyList(), emptyList(), versionsJson);

        // Mock responses for version resources
        mockResponse(resourceVersion1, containerLinks, emptyList(), createJson(resourceVersion1));
        mockResponse(resourceVersion2, containerLinks, emptyList(),
                createJson(resourceVersion2, resourceVersion2Child));
        mockResponse(resourceVersion3, containerLinks, emptyList(), createJson(resourceVersion3));
        mockResponse(resourceVersion2Child, containerLinks, emptyList(), createJson(resourceVersion2Child));

        exporter.run();

        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions/version1.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions/version2.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions/version2/vChild.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/1/fcr%3Aversions/version_original.jsonld")));
    }

    @Test
    public void testExportBinaryFromRepositoryRoot() throws Exception {
        final URI binaryResc = new URI(BASE_URI + "file1");
        final URI binaryRescMetadata = new URI(BASE_URI + "file1/fcr:metadata");
        final URI binaryRescVersions = new URI(BASE_URI + "file1/fcr:versions");
        final URI binaryRescVersion = new URI(BASE_URI + "file1/fcr:versions/version1");
        final URI binaryRescMetadataVersion = new URI(BASE_URI + "file1/fcr:versions/version1/fcr:metadata");

        mockResponse(binaryResc, binaryLinks, Arrays.asList(binaryRescMetadata), "binary");
        mockResponse(binaryRescVersion, binaryLinks, Arrays.asList(binaryRescMetadataVersion), "old binary");

        final List<URI> descriptionLinks = Arrays.asList(URI.create(RDF_SOURCE.getURI()));
        mockResponse(binaryRescMetadata, descriptionLinks, Collections.emptyList(), createJson(binaryRescMetadata));
        mockResponse(binaryRescMetadataVersion, descriptionLinks, Collections.emptyList(),
                createJson(binaryRescMetadataVersion));

        final String versionsJson = joinJsonArray(
                addVersionJson(new ArrayList<>(), binaryResc, binaryRescVersion, versionCreated, versionLabel));
        mockResponse(binaryRescVersions, emptyList(), emptyList(), versionsJson);

        mockResponse(rootResource, containerLinks, new ArrayList<>(),
                createJson(rootResource, REPOSITORY_ROOT, binaryResc));
        final URI rootVersionsUri = URI.create(rootResource.toString() + "/" + FCR_VERSIONS_PATH);
        ResponseMocker.mockGetResponseError(client, rootVersionsUri, 500);

        when(config.getResource()).thenReturn(rootResource);

        exporter.run();

        assertTrue(exporter.wroteFile(new File(basedir + "/rest/file1.binary")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/file1/fcr%3Ametadata.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/file1/fcr%3Aversions.jsonld")));
        assertTrue(exporter.wroteFile(new File(basedir + "/rest/file1/fcr%3Aversions/version1.binary")));
        assertTrue(exporter
                .wroteFile(new File(basedir + "/rest/file1/fcr%3Aversions/version1/fcr%3Ametadata.jsonld")));
    }

    private String createJson(final URI resource, final URI... children) {
        return createJson(resource, null, children);
    }

    private String createJson(final URI resource, final Resource type, final URI... children) {
        final StringBuilder json = new StringBuilder("{\"@id\":\"" + resource.toString() + "\"");
        if (type != null) {
            json.append(",\"@type\":[\"" + type.getURI() + "\"]");
        }
        if (children != null && children.length > 0) {
            json.append(",\"" + CONTAINS.getURI() + "\":[").append(Arrays.stream(children)
                    .map(child -> "{\"@id\":\"" + child.toString() + "\"}").collect(Collectors.joining(",")))
                    .append(']');
        }
        json.append('}');
        return json.toString();
    }

    private String joinJsonArray(final List<String> array) {
        return "[" + String.join(",", array) + "]";
    }

    private List<String> addVersionJson(final List<String> versions, final URI rescUri, final URI versionUri,
            final String label, final String timestamp) {
        final String versionJson = "{\"@id\":\"" + rescUri.toString() + "\"," + "\"" + HAS_VERSION.getURI()
                + "\":[{\"@id\":\"" + versionUri.toString() + "\"}]}," + "{\"@id\":\"" + versionUri.toString()
                + "\"," + "\"" + CREATED_DATE.getURI() + "\":[{" + "\"@value\":\"" + timestamp + "\","
                + "\"@type\": \"http://www.w3.org/2001/XMLSchema#dateTime\"}]," + "\"" + HAS_VERSION_LABEL.getURI()
                + "\":[{" + "\"@value\":\"" + label + " \"}]" + "}";
        versions.add(versionJson);
        return versions;
    }
}