org.ambraproject.rhino.RhinoTestHelper.java Source code

Java tutorial

Introduction

Here is the source code for org.ambraproject.rhino.RhinoTestHelper.java

Source

/*
 * Copyright (c) 2017 Public Library of Science
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction,
 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all copies or
 * substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
 * NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package org.ambraproject.rhino;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.net.URI;
import java.net.URL;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.ambraproject.rhino.config.RuntimeConfiguration;
import org.ambraproject.rhino.model.Article;
import org.ambraproject.rhino.model.Journal;
import org.ambraproject.rhino.model.Syndication;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Restrictions;
import org.springframework.orm.hibernate3.HibernateTemplate;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.beust.jcommander.internal.Nullable;
import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.gson.Gson;

/**
 * Miscellaneous fields and methods used in Rhino tests.
 */
public final class RhinoTestHelper {

    private static final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();

    static {
        factory.setNamespaceAware(true);
    }

    private RhinoTestHelper() {
    }

    /**
     * Parses an XML file.
     * 
     * @param xmlDataResource The XML URL data resource
     *
     * @return The {@link org.w3c.dom.Document Document}
     *
     * @throws ParserConfigurationException if a DocumentBuilder cannot be created which satisfies the
     *         configuration requested
     * @throws IOException if cannot process file
     * @throws SAXException if any parse errors occur
     */
    public static Document loadXMLFromString(URL xmlDataResource)
            throws ParserConfigurationException, IOException, SAXException {
        final File xmlFile = FileUtils.toFile(xmlDataResource);
        final Document document = loadXMLFromString(xmlFile);
        return document;
    }

    /**
     * Parses an XML file.
     * 
     * @param xml The XML file
     *
     * @return The {@link org.w3c.dom.Document Document}
     *
     * @throws ParserConfigurationException if a DocumentBuilder cannot be created which satisfies the
     *         configuration requested
     * @throws IOException if cannot process file
     * @throws SAXException if any parse errors occur
     */
    public static Document loadXMLFromString(File xml)
            throws ParserConfigurationException, IOException, SAXException {
        final DocumentBuilder builder = factory.newDocumentBuilder();
        final byte[] data = FileUtils.readFileToByteArray(xml);
        final Document document = builder.parse(new ByteArrayInputStream(data));
        return document;
    }

    /**
     * Mock input stream that yields a constant string and keeps track of whether it has been closed.
     * <p>
     * Closing the stream is not significant in this implementation, but one might want to test for
     * it.
     */
    public static class TestInputStream extends ByteArrayInputStream {
        private boolean isClosed;

        private TestInputStream(byte[] data) {
            super(data);
            isClosed = false;
        }

        public static TestInputStream of(byte[] data) {
            return new TestInputStream(data.clone());
        }

        public static TestInputStream of(String data) {
            return new TestInputStream(data.getBytes());
        }

        public boolean isClosed() {
            return isClosed;
        }

        @Override
        public void close() throws IOException {
            super.close();
            isClosed = true;
        }
    }

    /**
     * A file holding test input. An instance pre-loads the file contents into memory, and then makes
     * them available as needed through {@link TestInputStream}s or array dumps.
     */
    public static class TestFile {
        private final File fileLocation;
        private final byte[] fileData;

        public TestFile(File fileLocation) {
            this.fileLocation = fileLocation;
            try (InputStream stream = new FileInputStream(this.fileLocation)) {
                fileData = IOUtils.toByteArray(stream);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public TestInputStream read() {
            return new TestInputStream(fileData);
        }

        public byte[] getData() {
            return fileData.clone();
        }
    }

    /**
     * Class to implement a {@link RuntimeConfiguration.MultiBucketContentRepoEndpoint
     * MultiBucketContentRepoEndpoint}, which can be used for unit tests.
     */
    public static class TestMultiBucketContentRepoEndpoint
            implements RuntimeConfiguration.MultiBucketContentRepoEndpoint {

        private final ImmutableSet<String> allBuckets;

        private final ImmutableSet<String> secondaryBuckets;

        private Optional<String> defaultBucket = Optional.empty();

        private Optional<URI> address = Optional.empty();

        /**
         * Creates an instance of <code>TestMultiBucketContentRepoEndpoint</code>.
         *
         * @param buckets The list of <b>all</b> the buckets
         */
        public TestMultiBucketContentRepoEndpoint(String... buckets) {
            this(ImmutableSet.copyOf(buckets), Collections.emptySet() /* secondaryBuckets */);
        }

        /**
         * Creates an instance of <code>TestMultiBucketContentRepoEndpoint</code>.
         *
         * @param buckets The list of <b>all</b> the buckets
         * @param secondaryBuckets The list of secondary buckets
         */
        public TestMultiBucketContentRepoEndpoint(Set<String> buckets, Set<String> secondaryBuckets) {
            this(buckets, secondaryBuckets, null /* defaultBucket */, null /* address */);
        }

        /**
         * Creates an instance of <code>TestMultiBucketContentRepoEndpoint</code>.
         *
         * @param buckets The list of <b>all</b> the buckets
         * @param secondaryBuckets The list of secondary buckets
         * @param defaultBucket The default bucket
         * @param address The URI address
         */
        public TestMultiBucketContentRepoEndpoint(Set<String> buckets, Set<String> secondaryBuckets,
                @Nullable String defaultBucket, @Nullable URI address) {
            Preconditions.checkNotNull(buckets, "'buckets' must be specified.");
            Preconditions.checkNotNull(secondaryBuckets, "'secondaryBuckets' must be specified.");

            this.allBuckets = ImmutableSet.copyOf(buckets);
            this.secondaryBuckets = ImmutableSet.copyOf(secondaryBuckets);
            this.defaultBucket = Optional.ofNullable(defaultBucket);
            this.address = Optional.ofNullable(address);
        }

        /** Returns the URI. */
        @Override
        public URI getAddress() {
            return address.orElse(null);
        }

        /** Returns the default bucket. */
        @Override
        public String getDefaultBucket() {
            return defaultBucket.orElse("");
        }

        /** Returns the set of buckets. */
        @Override
        public ImmutableSet<String> getAllBuckets() {
            return allBuckets;
        }

        /** Returns the set of secondary buckets. */
        @Override
        public ImmutableSet<String> getSecondaryBuckets() {
            return secondaryBuckets;
        }
    }

    public static final ImmutableList<String> SAMPLE_ARTICLES = ImmutableList.of("pone.0038869"
    // More can be filled in here
    );

    /*
     * Each of these must belong to an article in SAMPLE_ARTICLES.
     */
    public static final ImmutableList<String> SAMPLE_ASSETS = ImmutableList.of("pone.0038869.g002.tif"
    // More can be filled in here
    );

    public static final Pattern ASSET_PATTERN = Pattern.compile("((.*)\\.[^.]+?)\\.([^.]+?)");

    public static final String prefixed(String doi) {
        return "10.1371/journal." + doi;
    }

    public static void deleteEntities(HibernateTemplate hibernateTemplate) {
        Collection<Class<?>> typesToDelete = ImmutableList.<Class<?>>of(Article.class, Syndication.class);
        for (Class<?> typeToDelete : typesToDelete) {
            List<?> allObjects = hibernateTemplate.findByCriteria(DetachedCriteria.forClass(typeToDelete));
            hibernateTemplate.deleteAll(allObjects);
        }
    }

    private static File getXmlPath(String doiStub) {
        return new File("src/test/resources/articles/" + doiStub + ".xml");
    }

    private static File getJsonPath(String doiStub) {
        return new File("src/test/resources/articles/" + doiStub + ".json");
    }

    public static Object[][] sampleArticles() {
        List<Object[]> cases = Lists.newArrayListWithCapacity(SAMPLE_ARTICLES.size());
        for (String doiStub : SAMPLE_ARTICLES) {
            Object[] sampleArticle = { prefixed(doiStub), getXmlPath(doiStub), getJsonPath(doiStub) };
            cases.add(sampleArticle);
        }
        return cases.toArray(new Object[cases.size()][]);
    }

    /**
     * Create a dummy journal with required non-null fields filled in.
     *
     * @param eissn the dummy journal's eIssn
     * @return a new dummy journal object
     */
    public static Journal createDummyJournal(String eissn) {
        Preconditions.checkNotNull(eissn);
        Journal journal = new Journal();
        String title = "Test Journal " + eissn;
        journal.setTitle(title);
        journal.setJournalKey(title.replaceAll("\\s|-", ""));
        journal.seteIssn(eissn);
        return journal;
    }

    public static TestInputStream alterStream(InputStream stream, String from, String to) throws IOException {
        String content;
        try {
            content = IOUtils.toString(stream, "UTF-8");
        } finally {
            stream.close();
        }
        content = content.replace(from, to);
        return TestInputStream.of(content);
    }

    public static void addExpectedJournals(HibernateTemplate hibernateTemplate) {
        final ImmutableSet<String> testCaseEissns = ImmutableSet.of("1932-6203");

        for (String eissn : testCaseEissns) {
            List<?> existing = hibernateTemplate
                    .findByCriteria(DetachedCriteria.forClass(Journal.class).add(Restrictions.eq("eIssn", eissn)));
            if (!existing.isEmpty()) {
                continue;
            }
            Journal journal = createDummyJournal(eissn);
            // hibernateTemplate.save(journal);
        }
    }

    // public static Archive createMockIngestible(ArticleIdentity articleId, InputStream xmlData,
    // List<ArticleAsset> referenceAssets) {
    // try {
    // try {
    // String archiveName = articleId.getLastToken() + ".zip";
    // InputStream mockIngestible = IngestibleUtil.buildMockIngestible(xmlData, referenceAssets);
    // return Archive.readZipFileIntoMemory(archiveName, mockIngestible);
    // } finally {
    // xmlData.close();
    // }
    // } catch (IOException e) {
    // throw new RuntimeException(e);
    // }
    // }

    // public static Stream<ArticleMetadata> createTestArticles(IngestionService ingestionService) {
    // return SAMPLE_ARTICLES.stream().map(doiStub -> createTestArticle(ingestionService, doiStub));
    // }
    //
    // public static ArticleMetadata createTestArticle(IngestionService ingestionService) {
    // return createTestArticle(ingestionService, SAMPLE_ARTICLES.get(0));
    // }

    // public static ArticleMetadata createTestArticle(IngestionService ingestionService, String
    // doiStub) {
    // ArticleIdentity articleId = ArticleIdentity.create(RhinoTestHelper.prefixed(doiStub));
    // RhinoTestHelper.TestFile sampleFile = new RhinoTestHelper.TestFile(getXmlPath(doiStub));
    // String doi = articleId.getIdentifier();
    //
    // byte[] sampleData;
    // try {
    // sampleData = IOUtils.toByteArray(RhinoTestHelper.alterStream(sampleFile.read(), doi, doi));
    // } catch (IOException e) {
    // throw new RuntimeException(e);
    // }
    //
    // Article reference = readReferenceCase(getJsonPath(doiStub));
    //
    // RhinoTestHelper.TestInputStream input = RhinoTestHelper.TestInputStream.of(sampleData);
    // Archive mockIngestible = createMockIngestible(articleId, input, reference.getAssets());
    // ArticleIngestion ingestion;
    // try {
    // ingestion = ingestionService.ingest(mockIngestible);
    // } catch (IOException e) {
    // throw new RuntimeException(e);
    // }
    // return null; // TODO: Recover ArticleMetadata from ArticleIngestionIdentifier
    // }

    public static Article readReferenceCase(File jsonFile) {
        Preconditions.checkNotNull(jsonFile);
        Article article;
        try (Reader input = new BufferedReader(new FileReader(jsonFile))) {
            article = new Gson().fromJson(input, Article.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return article;
    }

}