org.ambraproject.article.service.IngesterTest.java Source code

Java tutorial

Introduction

Here is the source code for org.ambraproject.article.service.IngesterTest.java

Source

/*
 * $HeadURL$
 * $Id$
 *
 * Copyright (c) 2006-2011 by Public Library of Science
 * http://plos.org
 * http://ambraproject.org
 *
 * Licensed 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.ambraproject.article.service;

import org.ambraproject.admin.AdminBaseTest;
import org.ambraproject.models.Article;
import org.ambraproject.models.ArticleAsset;
import org.ambraproject.models.ArticleRelationship;
import org.ambraproject.models.Category;
import org.ambraproject.models.Issue;
import org.ambraproject.models.Journal;
import org.ambraproject.service.article.NoSuchArticleIdException;
import org.ambraproject.service.article.DuplicateArticleIdException;
import org.apache.commons.io.FileUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipFile;

import static org.testng.Assert.*;

/**
 * Test for implementation of ingester.  Working directory for the test should be set to the ambra webapp home
 * directory
 *
 * @author Alex Kudlick Date: 5/11/11
 *         <p/>
 *         org.ambraproject.article.service
 */
public class IngesterTest extends AdminBaseTest {

    @Autowired
    protected Ingester ingester;

    @Qualifier("filestoreDir")
    @Autowired
    protected String fileStoreDir;

    private static final String[] ingestedDirectories = new String[] { "pmed.0050082", "pgen.1002295",
            "pntd.0000241", "pmed.1001027", "image.pcol.v01.i10" };

    //save the journals in the articles we're ingesting
    @BeforeMethod
    public void saveJournals() {
        for (String eIssn : Arrays.asList("1549-1676", "1935-2735", "1553-7404")) {
            Journal journal = new Journal();
            journal.seteIssn(eIssn);
            dummyDataStore.store(journal);
        }
    }

    //clean up after the test
    @AfterClass
    public void deleteIngestedDir() throws IOException {
        File baseDir = new File(fileStoreDir, "10.1371");
        if (baseDir.exists()) {
            for (String dir : ingestedDirectories) {
                FileUtils.deleteDirectory(new File(baseDir, dir));
            }
        }
    }

    @Test(dataProviderClass = SampleArticleData.class, dataProvider = "sampleArticle")
    public void testIngest(ZipFile ingestArchive, Article expectedArticle) throws Exception {
        Long[] relatedArticleIds = storeRelatedArticles();
        //Article Relationship that should be included in the ingested article
        ArticleRelationship relationship3 = new ArticleRelationship();
        relationship3.setOtherArticleDoi("info:doi/10.1371/journal.pbio.0020034");
        relationship3.setType("companion");
        relationship3.setParentArticle(expectedArticle);
        expectedArticle.getRelatedArticles().add(relationship3);

        Article ingestedArticle = ingester.ingest(ingestArchive, false);
        compareArticles(ingestedArticle, expectedArticle);

        Article storedArticle = dummyDataStore.get(Article.class, ingestedArticle.getID());
        assertNotNull(storedArticle, "Article wasn't stored to the db");
        compareArticles(storedArticle, expectedArticle);
        assertNotNull(storedArticle.getCreated(), "Article didn't get create date set");

        checkRelatedArticles(relatedArticleIds, ingestedArticle);
    }

    private void checkRelatedArticles(Long[] otherArticleIds, Article ingestedArticle) {
        for (Long id : otherArticleIds) {
            Article otherArticle = dummyDataStore.get(Article.class, id);
            boolean foundMatch = false;
            for (ArticleRelationship relationship : otherArticle.getRelatedArticles()) {
                if (relationship.getOtherArticleDoi().equals(ingestedArticle.getDoi())) {
                    assertEquals(relationship.getOtherArticleID(), ingestedArticle.getID(),
                            "Related article didn't get 'OtherArticleID' set correctly");
                    foundMatch = true;
                    break;
                }
            }
            assertTrue(foundMatch, "Article " + otherArticle + " didn't get a relationship linking to new article");
        }
    }

    /**
     * Store articles that the ones to be ingested relate to, so we can check the reciprocal linking on related articles
     * @return an array  of ids for articles that should get relationships added to the new article
     */
    public Long[] storeRelatedArticles() {
        //First article to relate to with an existing 'relationship' object. This should get it's 'otherArticleID' set
        Article articleWithExistingRelationship = new Article();
        articleWithExistingRelationship.setDoi("info:doi/10.1371/journal.pmed.0050061");
        List<ArticleRelationship> relationships = new ArrayList<ArticleRelationship>(1);
        relationships.add(new ArticleRelationship());
        relationships.get(0).setParentArticle(articleWithExistingRelationship);
        relationships.get(0).setOtherArticleDoi("info:doi/10.1371/journal.pmed.0050082");
        relationships.get(0).setType("companion");
        articleWithExistingRelationship.setRelatedArticles(relationships);
        Long id1 = Long.valueOf(dummyDataStore.store(articleWithExistingRelationship));

        //Second article to relate to.  This should get a relationship added
        Article articleWithNoRelationship = new Article();
        articleWithNoRelationship.setDoi("info:doi/10.1371/journal.pbio.0000064");
        Long id2 = Long.valueOf(dummyDataStore.store(articleWithNoRelationship));

        //Third article that relates to new article, but is not linked to by the new article
        Article articleWithRelationshipNotLinkedTo = new Article();
        articleWithRelationshipNotLinkedTo.setDoi("info:doi/10.1371/journal.pbio.0020034");
        List<ArticleRelationship> relationships1 = new ArrayList<ArticleRelationship>(1);
        relationships1.add(new ArticleRelationship());
        relationships1.get(0).setOtherArticleDoi("info:doi/10.1371/journal.pmed.0050082");
        relationships1.get(0).setType("companion");
        relationships1.get(0).setParentArticle(articleWithRelationshipNotLinkedTo);
        articleWithRelationshipNotLinkedTo.setRelatedArticles(relationships1);

        Long id3 = Long.valueOf(dummyDataStore.store(articleWithRelationshipNotLinkedTo));
        return new Long[] { id1, id2, id3 };
    }

    @Test(dataProviderClass = SampleArticleData.class, dataProvider = "sampleArticle", dependsOnMethods = "testIngest", expectedExceptions = DuplicateArticleIdException.class)
    public void testDuplicateArticleException(ZipFile ingestArchive, Article notUsed)
            throws DuplicateArticleIdException, IngestException {
        ingester.ingest(ingestArchive, false);
    }

    @Test(dataProviderClass = SampleArticleData.class, dataProvider = "sampleArticle", dependsOnMethods = {
            "testIngest", "testDuplicateArticleException" })
    public void testIngestWithForce(ZipFile ingestArchive, Article expectedArticle)
            throws DuplicateArticleIdException, IngestException {
        //Article Relationship that should be included in the ingested article
        ArticleRelationship relationship3 = new ArticleRelationship();
        relationship3.setOtherArticleDoi("info:doi/10.1371/journal.pbio.0020034");
        relationship3.setType("companion");
        relationship3.setParentArticle(expectedArticle);
        expectedArticle.getRelatedArticles().add(relationship3);

        Long id = ingester.ingest(ingestArchive, true).getID();
        Article storedArticle = dummyDataStore.get(Article.class, id);
        assertNotNull(storedArticle, "Article wasn't stored to the db");
        compareArticles(storedArticle, expectedArticle);
    }

    //Check that ingest didn't create duplicate categories 
    @Test(dependsOnMethods = { "testIngestWithForce", "testIngestWithAssetsAndForce" })
    public void testIngestDoesntCreateDuplicateCategories() {
        Set<Category> categories = new HashSet<Category>(9);
        List<Category> storedCategories = dummyDataStore.getAll(Category.class);
        assertTrue(storedCategories.size() > 0, "didn't store any categories to the database");
        for (Category category : storedCategories) {
            assertFalse(categories.contains(category), "Stored duplicate category " + category);
            categories.add(category);
        }
    }

    @Test(dataProviderClass = SampleArticleData.class, dataProvider = "sampleAssets", dependsOnMethods = {
            "testIngestWithForce" }, alwaysRun = true)
    public void testIngestWithAssets(ZipFile archive, List<ArticleAsset> expectedAssets)
            throws DuplicateArticleIdException, IngestException, NoSuchArticleIdException {
        final Article article = ingester.ingest(archive, false);
        List<ArticleAsset> actualAssets = article.getAssets();

        assertNotNull(actualAssets, "had null list of assets");
        assertEquals(actualAssets.size(), expectedAssets.size(), "incorrect number of assets");
        for (int i = 0; i < actualAssets.size(); i++) {
            compareAssets(actualAssets.get(i), expectedAssets.get(i));
        }

        List<ArticleAsset> storedAssets = null;
        try {
            storedAssets = dummyDataStore.get(Article.class, article.getID()).getAssets();
        } catch (NullPointerException e) {
            fail("Article wasn't stored to the db");
        }

        assertNotNull(storedAssets, "stored article had null list of assets");
        assertEquals(storedAssets.size(), expectedAssets.size(), "stored article had incorrect number of assets");
        for (int i = 0; i < storedAssets.size(); i++) {
            compareAssets(storedAssets.get(i), expectedAssets.get(i));
        }

    }

    @Test(dataProviderClass = SampleArticleData.class, dataProvider = "sampleAssets", dependsOnMethods = "testIngestWithAssets")
    public void testIngestWithAssetsAndForce(ZipFile archive, List<ArticleAsset> notUsed)
            throws DuplicateArticleIdException, IngestException {
        ingester.ingest(archive, true);
    }

    @DataProvider(name = "imageArticle")
    public Object[][] getImageArticle() throws Exception {
        File testFile = new File(
                IngesterTest.class.getClassLoader().getResource("ingest/test-ingest-image-article.zip").toURI());
        ZipFile archive = new ZipFile(testFile);
        //put the article in the db so we can reingest it
        Article article = new Article();
        article.setDoi("info:doi/10.1371/image.pcol.v01.i10");
        dummyDataStore.store(article);

        Issue issue = new Issue();
        issue.setIssueUri("info:doi/10.1371/issue.pcol.v01.i01");
        issue.setImageUri(article.getDoi());
        issue.setDescription("This description should get overwritten");
        Long issueId = Long.valueOf(dummyDataStore.store(issue));

        return new Object[][] { { archive, issueId } };
    }

    @Test(dataProvider = "imageArticle", dependsOnMethods = { "testIngestWithForce",
            "testIngestDoesntCreateDuplicateCategories" })
    public void testReIngestImageArticle(ZipFile archive, Long issueId)
            throws DuplicateArticleIdException, IngestException {
        Article article = ingester.ingest(archive, true);
        Issue issue = dummyDataStore.get(Issue.class, issueId);
        assertEquals(issue.getDescription(), article.getDescription(),
                "issue for image article didn't have description updated");
    }

    /**
     * Regression test for the bug described <a href="https://developer.plos.org/jira/browse/NHOPE-222">here</a>.  Ingest
     * an article, then add images to the zip, and try to reingest.
     *
     * @param originalArchive
     * @param alteredArchive
     * @param expectedPartsDois
     * @throws Exception
     */
    @Test(dataProviderClass = SampleArticleData.class, dataProvider = "alteredZip", groups = "regressionTest", dependsOnMethods = {
            "testIngest", "testIngestWithForce", "testIngestWithAssets", "testIngestWithAssetsAndForce",
            "testIngestDoesntCreateDuplicateCategories" }, alwaysRun = true)
    public void testForceIngestAfterZipHasChanged(ZipFile originalArchive, ZipFile alteredArchive,
            List<String> expectedPartsDois) throws Exception {

        Article article = ingester.ingest(originalArchive, false); //get the original article in the db
        try {
            article = ingester.ingest(alteredArchive, true);//force ingestion
        } catch (Exception e) {
            fail("There was an error ingesting the altered archive", e);
        }

        Article storedArticle = dummyDataStore.get(Article.class, article.getID());

        assertEquals(article.getAssets().size(), expectedPartsDois.size(), "stored incorrect number of parts");
        //get the parts' ids into a list to compare them
        List<String> actualPartsDois = new ArrayList<String>(expectedPartsDois.size());
        for (ArticleAsset part : storedArticle.getAssets()) {
            assertNotNull(part, "parts didn't get stored to the db");
            actualPartsDois.add(part.getDoi());
        }
        assertEquals(actualPartsDois.toArray(), expectedPartsDois.toArray(), "stored incorrect part ids");

        try {
            ingester.ingest(originalArchive, true); //re-ingest the original archive
        } catch (Exception e) {
            fail("There was an error reingesting the original archive", e);
        }
    }
}