/* * $HeadURL$ * $Id$ * Copyright (c) 2006-2013 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.0Unless 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.service.article; import org.ambraproject.action.BaseTest; import org.ambraproject.filestore.FileStoreService; import org.ambraproject.models.Article; import org.ambraproject.models.ArticleAsset; import org.ambraproject.models.CitedArticle; import org.ambraproject.models.CitedArticleAuthor; import org.ambraproject.service.xml.XMLService; import org.ambraproject.views.AuthorView; import org.ambraproject.views.article.ArticleInfo; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.springframework.beans.factory.annotation.Autowired; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Date; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertTrue; public class FetchArticleServiceTest extends BaseTest { @Autowired protected FetchArticleService fetchArticleService; @Autowired protected ArticleService articleService; @Autowired protected FileStoreService fileStoreService; @Autowired protected XMLService xmlService; @DataProvider(name = "articlesForCorrespondingTest") public Object[][] getArticlesForCorrespondingTest() { //<corresp id="cor1">* E-mail: // <email xlink:type="simple">maud.hertzog@ibcg.biotoul.fr</email> (MH); // <email xlink:type="simple">philippe.chavrier@curie.fr</email> (PC)</corresp> ArticleInfo a1 = new ArticleInfo("info:doi/10.1371/journal.pone.0052627"); List<String> authors1 = new ArrayList<String>() {{ add("<a href=\"mailto:maud.hertzog@ibcg.biotoul.fr\">maud.hertzog@ibcg.biotoul.fr</a> (MH)"); add("<a href=\"mailto:philippe.chavrier@curie.fr\">philippe.chavrier@curie.fr</a> (PC)"); }}; ArticleInfo a2 = new ArticleInfo("info:doi/10.1371/journal.pone.0023160"); List<String> authors2 = new ArrayList<String>() {{ add("<a href=\"mailto:bach@bu.edu\">bach@bu.edu</a>"); }}; ArticleInfo a3 = new ArticleInfo("info:doi/10.1371/image.ppat.v04.i11"); List<String> authors3 = new ArrayList<String>(); return new Object[][] { { a1, authors1 }, { a2, authors2 }, { a3, authors3 } }; } @DataProvider(name = "snippetsForCorrespondingTest") public Object[][] getSnippetsForCorrespondingTest() throws FileNotFoundException, IOException { return new Object[][] { { "<corresp id=\"cor1\">* To whom correspondence should be addressed. E-mail: <email xlink:type=\"simple\">david.schatz@yale.edu</email></corresp>\n", new String[] { "<a href=\"mailto:david.schatz@yale.edu\">david.schatz@yale.edu</a>" } }, { "<corresp id=\"cor1\">* To whom correspondence should be addressed. E-mail: <email xlink:type=\"simple\">jeisen@tigr.org</email></corresp>\n", new String[] { "<a href=\"mailto:jeisen@tigr.org\">jeisen@tigr.org</a>" } }, { "<corresp id=\"cor1\">* E-mail: <email xlink:type=\"simple\">ningolia@fas.harvard.edu</email>\n", new String[] { "<a href=\"mailto:ningolia@fas.harvard.edu\">ningolia@fas.harvard.edu</a>" } }, { "<corresp id=\"cor1\">* To whom correspondence should be addressed. E-mail: <email xlink:type=\"simple\">jurka@girinst.org</email> (JJ), Email: <email xlink:type=\"simple\">larionov@mail.nih.gov</email> (VL)</corresp>\n", new String[] { "<a href=\"mailto:jurka@girinst.org\">jurka@girinst.org</a> (JJ)", "<a href=\"mailto:larionov@mail.nih.gov\">larionov@mail.nih.gov</a> (VL)" } }, { "<corresp id=\\\"cor1\\\">* To whom correspondence should be addressed. E-mail: <email xlink:type=\"simple\">jbroach@molbio.princeton.edu</email></corresp>\n", new String[] { "<a href=\"mailto:jbroach@molbio.princeton.edu\">jbroach@molbio.princeton.edu</a>", } }, { "<corresp id=\"cor1\">*To whom correspondence should be addressed. E-mail: <email xlink:type=\"simple\">zon@enders.tch.harvard.edu</email></corresp>\n", new String[] { "<a href=\"mailto:zon@enders.tch.harvard.edu\">zon@enders.tch.harvard.edu</a>", } }, { "<corresp id=\"cor1\">* E-mail: <email xlink:type=\"simple\">Kopan@wustl.edu</email></corresp>\n", new String[] { "<a href=\"mailto:Kopan@wustl.edu\">Kopan@wustl.edu</a>",} }, { "<corresp id=\"n101\">* To whom correspondence should be addressed. E-mail: <email xlink:type=\"simple\">nzr6@cdc.gov</email>\n", new String[] { "<a href=\"mailto:nzr6@cdc.gov\">nzr6@cdc.gov</a>", } }, { "<corresp id=\"cor1\">* E-mail: <email xlink:type=\"simple\">jeff.leonard@oregonstate.edu</email></corresp>\n", new String[] { "<a href=\"mailto:jeff.leonard@oregonstate.edu\">jeff.leonard@oregonstate.edu</a>", } } }; } @DataProvider(name = "articlesWithDummyAffils") public Object[][] getArticlesWithDummyAffils() { //Test an author with a suffix on their name ArticleInfo a1 = new ArticleInfo("info:doi/10.1371/journal.pone.0002879"); List<AuthorView> authors1 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("John M.") .setSurnames("Logsdon") .setSuffix("Jr") .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding("<span class=\"email\">* E-mail:</span> <a href=\"mailto:john-logsdon@uiowa.edu\">john-logsdon@uiowa.edu</a>") .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Department of Biology test"); }}) .setCustomFootnotes(null) .build()); }}; //Test corresponding author ArticleInfo a2 = new ArticleInfo("info:doi/10.1371/journal.pbio.1001335"); List<AuthorView> authors2 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("Mariano") .setSurnames("Carrión-Vázquez") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding("<span class=\"email\">* E-mail:</span> <a href=\"mailto:mcarrion@cajal.csic.es\">mcarrion@cajal.csic.es</a>") .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Instituto Cajal"); add("Instituto Madrileño"); }}) .setCustomFootnotes(null) .build()); }}; //Test deceased author ArticleInfo a3 = new ArticleInfo("info:doi/10.1371/journal.pntd.0001165"); List<AuthorView> authors3 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("Nicholas J. S.") .setSurnames("Lwambo") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(true) .setCorresponding(null) .setRelatedFootnote(false) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("National Institute for Medical Research, Mwanza Medical Research Centre, Mwanza, Tanzania"); }}) .setCustomFootnotes(null) .build()); }}; //additional sets of equally contributing authors. ArticleInfo a4 = new ArticleInfo("info:doi/10.1371/journal.pone.0023160"); List<AuthorView> authors4 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("Markus M.") .setSurnames("Bachschmid") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(true) .setCorresponding("<span class=\"email\">* E-mail:</span> <a href=\"mailto:bach@bu.edu\">bach@bu.edu</a>") .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Vascular Biology Section, Boston University Medical Center, Boston, Massachusetts, United States of America"); }}) .setCustomFootnotes(new ArrayList<String>() {{ add("<p><span class=\"rel-footnote\">¶</span>These authors also contributed equally to this work.</p>"); }}) .build()); add(AuthorView.builder() .setGivenNames("David R.") .setSurnames("Pimental") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setCorresponding(null) .setRelatedFootnote(true) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Myocardial Biology Unit, Boston University Medical Center, Boston, Massachusetts, United States of America"); }}) .setCustomFootnotes(new ArrayList<String>() {{ add("<p><span class=\"rel-footnote\">¶</span>These authors also contributed equally to this work.</p>"); }}) .build()); }}; //Test alternate address ArticleInfo a5 = new ArticleInfo("info:doi/10.1371/journal.pone.0020568"); List<AuthorView> authors5 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("Oliver") .setSurnames("Liesenfeld") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setCorresponding(null) .setRelatedFootnote(false) .setCurrentAddresses(new ArrayList<String>() {{ add("Current address: Roche Molecular Diagnostics, Pleasanton, California, United States of America"); }}) .setAffiliations(new ArrayList<String>() {{ add("Institute of Microbiology and Hygiene, Charité Universitätsmedizin Berlin, Berlin, Germany"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("Iana") .setSurnames("Parvanova") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setCorresponding(null) .setRelatedFootnote(false) .setCurrentAddresses(new ArrayList<String>() {{ add("Current address: Bavarian Research Alliance GmbH (BayFOR), Munich, Germany"); }}) .setAffiliations(new ArrayList<String>() {{ add("Institute for Genetics, University of Cologne, Cologne, Germany"); }}) .setCustomFootnotes(null) .build()); }}; //Test 'other' author attribute ArticleInfo a6 = new ArticleInfo("info:doi/10.1371/journal.pone.0032315"); List<AuthorView> authors6 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("the Danish SAB Study Group Consortium") .setSurnames(null) .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setCorresponding(null) .setCurrentAddresses(null) .setAffiliations(null) .setRelatedFootnote(false) .setCustomFootnotes(new ArrayList<String>() {{ add("<p>Membership of the Danish SAB Study Group Consortium is provided in the Acknowledgments.</p>"); }}) .build()); }}; //Additional test for corresponding author ArticleInfo a7 = new ArticleInfo("info:doi/10.1371/journal.pmed.0020073"); List<AuthorView> authors7 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("William") .setSurnames("Pao") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(true) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding("<span class=\"email\">*</span>To whom correspondence should be addressed. E-mail: <a href=\"mailto:paow@mskcc.org\">paow@mskcc.org</a>") .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Program in Cancer Biology and Genetics, Memorial Sloan-Kettering Cancer Center, New York, New York, United States of America"); add("Thoracic Oncology Service, Department of Medicine, Memorial Sloan-Kettering Cancer Center, New York, New York, United States of America"); }}) .setCustomFootnotes(null) .build()); }}; //Test for articles with multiple corresponding authors ArticleInfo a8 = new ArticleInfo("info:doi/10.1371/journal.pone.0029914"); List<AuthorView> authors8 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("Monica E.") .setSurnames("Embers") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding("<span class=\"email\">* E-mail:</span> <a href=\"mailto:members@tulane.edu\">members@tulane.edu</a> (MEE); <a href=\"mailto:Philipp@tulane.edu\">Philipp@tulane.edu</a> (MTP)") .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Divisions of Bacteriology & Parasitology, Tulane National Primate Research Center, Tulane University Health Sciences Center, Covington, Louisiana, United States of America"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("Mario T.") .setSurnames("Philipp") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding("<span class=\"email\">* E-mail:</span> <a href=\"mailto:members@tulane.edu\">members@tulane.edu</a> (MEE); <a href=\"mailto:Philipp@tulane.edu\">Philipp@tulane.edu</a> (MTP)") .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Divisions of Bacteriology & Parasitology, Tulane National Primate Research Center, Tulane University Health Sciences Center, Covington, Louisiana, United States of America"); }}) .setCustomFootnotes(null) .build()); }}; //Test for articles with 'on behalf of' node defined ArticleInfo a9 = new ArticleInfo("info:doi/10.1371/journal.pone.0047391"); List<AuthorView> authors9 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("David") .setSurnames("Dalmau") .setSuffix(null) .setOnBehalfOf("on behalf of Busia OR Study Group") .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding("<span class=\"email\">* E-mail:</span> <a href=\"mailto:ddalmau@mutuaterrassa.cat\">ddalmau@mutuaterrassa.cat</a>") .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Hospital Universitari MútuaTerrassa, Medicine Department, Terrassa, Spain"); add("Fundació Docència i Recerca MutuaTerrassa, Terrassa, Spain"); }}) .setCustomFootnotes(null) .build()); }}; //Test for articles with 'on behalf of' node defined + plus extra data ArticleInfo a10 = new ArticleInfo("info:doi/10.1371/journal.pone.0050788"); List<AuthorView> authors10 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("François") .setSurnames("Goffinet") .setSuffix(null) .setOnBehalfOf("for the EVAPRIMA group") .setEqualContrib(false) .setDeceased(false) .setCorresponding(null) .setRelatedFootnote(false) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("INSERM UMR S953, Epidemiological Research Unit on Perinatal Health and Women’s and Children’s Health, Pierre et Marie Curie University, Paris, France"); add("Department of Obstetrics and Gynaecology, Port-Royal Maternity, Cochin Saint-Vincent-de-Paul Hospital, Assistance Publique des Hopitaux de Paris, Université Paris Descartes, Sorbonne Paris Cité, Paris, France"); add("Premup Foundation, Paris, France"); }}) .setCustomFootnotes(new ArrayList<String>() {{ add("<p>Membership of the EVAPRIMA group is provided in the Acknowledgments.</p>"); }}) .build()); }}; //Test for articles with multiple corresponding authors ArticleInfo a11 = new ArticleInfo("info:doi/10.1371/journal.pone.0047597"); List<AuthorView> authors11 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("Allison R.") .setSurnames("Baker") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(true) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(new ArrayList<String>() {{ add("Current address: Clinical Services Group, Hospital Corporations of America, Nashville, Tennessee, United States of America"); }}) .setAffiliations(new ArrayList<String>() {{ add("Department of Epidemiology and Biostatistics, Case Western Reserve University, Cleveland, Ohio, United States of America"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("Feiyou") .setSurnames("Qiu") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(true) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Department of Epidemiology and Biostatistics, Case Western Reserve University, Cleveland, Ohio, United States of America"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("April Kaur") .setSurnames("Randhawa") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Department of Medicine, University of Washington School of Medicine, Seattle, Washington, United States of America"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("David J.") .setSurnames("Horne") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Department of Medicine, University of Washington School of Medicine, Seattle, Washington, United States of America"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("Mark D.") .setSurnames("Adams") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(new ArrayList<String>() {{ add("Current address: J. Craig Venter Institute, San Diego, California, United States of America"); }}) .setAffiliations(new ArrayList<String>() {{ add("Department of Genetics and Center for Proteomics and Bioinformatics, Case Western Reserve University, Cleveland, Ohio, United States of America"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("Muki") .setSurnames("Shey") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("South African Tuberculosis Vaccine Initiative, Institute of Infectious Diseases and Molecular Medicine and School of Child and Adolescent Health, University of Cape Town, South Africa"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("Jill") .setSurnames("Barnholtz-Sloan") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Department of Epidemiology and Biostatistics, Case Western Reserve University, Cleveland, Ohio, United States of America"); add("Case Comprehensive Cancer Center, Case Western Reserve University, Cleveland, Ohio, United States of America"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("Harriet") .setSurnames("Mayanja-Kizza") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Uganda – Case Western Reserve University Research Collaboration, Cleveland, Ohio, United States of America, and Kampala, Uganda"); add("Makerere University School of Medicine and Mulago Hospital, Kampala, Uganda"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("Gilla") .setSurnames("Kaplan") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Public Health Research Institute, University of Medicine and Dentistry of New Jersey, Newark, New Jersey, United States of America"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("Willem A.") .setSurnames("Hanekom") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("South African Tuberculosis Vaccine Initiative, Institute of Infectious Diseases and Molecular Medicine and School of Child and Adolescent Health, University of Cape Town, South Africa"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("W. Henry") .setSurnames("Boom") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Department of Medicine, Case Western Reserve University, Cleveland, Ohio, United States of America"); add("Uganda – Case Western Reserve University Research Collaboration, Cleveland, Ohio, United States of America, and Kampala, Uganda"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("Thomas R.") .setSurnames("Hawn") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(true) .setCorresponding(null) .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Department of Medicine, University of Washington School of Medicine, Seattle, Washington, United States of America"); }}) .setCustomFootnotes(new ArrayList<String>() {{ add("<p><span class=\"rel-footnote\">¶</span>These authors are joint senior authors on this work.</p>"); }}) .build()); add(AuthorView.builder() .setGivenNames("Catherine M.") .setSurnames("Stein") .setSuffix(null) .setOnBehalfOf("for the Tuberculosis Research Unit (TBRU) and South African Tuberculosis Vaccine Initiative Team (SATVI)") .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(true) .setCorresponding("<span class=\"email\">* E-mail:</span> <a href=\"mailto:catherine.stein@case.edu\">catherine.stein@case.edu</a>") .setCurrentAddresses(null) .setAffiliations(new ArrayList<String>() {{ add("Department of Epidemiology and Biostatistics, Case Western Reserve University, Cleveland, Ohio, United States of America"); add("Uganda – Case Western Reserve University Research Collaboration, Cleveland, Ohio, United States of America, and Kampala, Uganda"); }}) .setCustomFootnotes(new ArrayList<String>() {{ add("<p><span class=\"rel-footnote\">¶</span>These authors are joint senior authors on this work.</p>"); }}) .build()); }}; //Test for multiple addresses ArticleInfo a12 = new ArticleInfo("info:doi/10.1371/journal.pone.0052627"); List<AuthorView> authors12 = new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("Maud") .setSurnames("Hertzog") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding("<span class=\"email\">* E-mail:</span> <a href=\"mailto:maud.hertzog@ibcg.biotoul.fr\">maud.hertzog@ibcg.biotoul.fr</a> (MH); <a href=\"mailto:philippe.chavrier@curie.fr\">philippe.chavrier@curie.fr</a> (PC)") .setCurrentAddresses(new ArrayList<String>() {{ add("Current address: Laboratoire de Microbiologie et Génétique Moléculaire, LMGM-CNRS UMR 5100, Université Paul Sabatier, Toulouse, France"); add("CNRS, UMR 6061, Institut Génétique et Développement de Rennes, Université Rennes 1, UEB, IFR 140, Rennes, France"); }}) .setAffiliations(new ArrayList<String>() {{ add("Membrane and Cytoskeleton Dynamics, Institut Curie, Research Center, CNRS- UMR144, Paris, France"); }}) .setCustomFootnotes(null) .build()); add(AuthorView.builder() .setGivenNames("Pedro") .setSurnames("Monteiro") .setSuffix(null) .setOnBehalfOf(null) .setEqualContrib(false) .setDeceased(false) .setRelatedFootnote(false) .setCorresponding(null) .setCurrentAddresses(new ArrayList<String>() {{ add("Current address: Laboratoire de Microbiologie et Génétique Moléculaire, LMGM-CNRS UMR 5100, Université Paul Sabatier, Toulouse, France"); }}) .setAffiliations(new ArrayList<String>() {{ add("Membrane and Cytoskeleton Dynamics, Institut Curie, Research Center, CNRS- UMR144, Paris, France"); }}) .setCustomFootnotes(null) .build()); }}; return new Object[][] { { a1, authors1 }, { a2, authors2 }, { a3, authors3 }, { a4, authors4 } , { a5, authors5 }, { a6, authors6 }, { a7, authors7 }, { a8, authors8 }, { a9, authors9 }, { a10, authors10 }, { a11, authors11 }, { a12, authors12 } }; } @DataProvider(name = "articleInfos") public Object[][] getArticleInfos() { // nlm 2.0 article String doi1 = "info:doi/10.1371/journal.pone.0023176"; Article article1 = new Article(); article1.setState(Article.STATE_ACTIVE); article1.setDoi(doi1); article1.setTitle("Fibronectin Unfolding Revisited: Modeling Cell Traction-Mediated Unfolding of the Tenth Type-III Repeat"); article1.seteIssn("1932-6203"); article1.setArchiveName("archive name from the database"); article1.setDescription("description from the database"); article1.setAssets(new ArrayList<ArticleAsset>(1)); ArticleAsset asset1 = new ArticleAsset(); asset1.setDoi(doi1); asset1.setExtension("XML"); asset1.setContentType("text/xml"); article1.getAssets().add(asset1); article1.setCitedArticles(new ArrayList<CitedArticle>()); CitedArticle citedArticle1 = new CitedArticle(); citedArticle1.setKey("1"); citedArticle1.setYear(1982); citedArticle1.setDisplayYear("1982"); citedArticle1.setVolumeNumber(115); citedArticle1.setVolume("115"); citedArticle1.setIssue("5"); citedArticle1.setTitle("Estimating household and community transmission parameters for influenza."); citedArticle1.setPages("736-51"); citedArticle1.seteLocationID("736"); citedArticle1.setJournal("Am J Epidemiol"); citedArticle1.setCitationType("http://purl.org/net/nknouf/ns/bibtex#Article"); article1.getCitedArticles().add(citedArticle1); dummyDataStore.store(article1); ArticleInfo articleInfo1 = new ArticleInfo(doi1); articleInfo1.setCitedArticles(new ArrayList<CitedArticle>()); articleInfo1.getCitedArticles().add(citedArticle1); // nlm 3.0 article String doi2 = "info:doi/10.1371/journal.pcbi.1002692"; Article article2 = new Article(); article2.setState(Article.STATE_ACTIVE); article2.setDoi(doi2); article2.setTitle("Connecting Macroscopic Observables and Microscopic Assembly Events in Amyloid Formation Using Coarse Grained Simulations"); article2.seteIssn("1553-7358"); article2.setArchiveName("archive name from the database"); article2.setDescription("description from the database"); article2.setAssets(new ArrayList<ArticleAsset>(1)); ArticleAsset asset2 = new ArticleAsset(); asset2.setDoi(doi2); asset2.setExtension("XML"); asset2.setContentType("text/xml"); article2.getAssets().add(asset2); article2.setCitedArticles(new ArrayList<CitedArticle>()); CitedArticleAuthor citedArticleAuthor = new CitedArticleAuthor(); citedArticleAuthor.setGivenNames("W"); citedArticleAuthor.setSurnames("Balch"); CitedArticle citedArticle2 = new CitedArticle(); citedArticle2.setKey("1"); citedArticle2.setYear(2003); citedArticle2.setDisplayYear("2003"); citedArticle2.setVolumeNumber(161); citedArticle2.setVolume("161"); citedArticle2.setTitle("Amyloid as a natural product"); citedArticle2.setPages("461-462"); citedArticle2.seteLocationID("461"); citedArticle2.setJournal("J Cell Biol"); citedArticle2.setCitationType("http://purl.org/net/nknouf/ns/bibtex#Article"); article2.getCitedArticles().add(citedArticle2); List<CitedArticleAuthor> authors = new ArrayList<CitedArticleAuthor>(); authors.add(citedArticleAuthor); citedArticle2.setAuthors(authors); dummyDataStore.store(article2); ArticleInfo articleInfo2 = new ArticleInfo(doi2); articleInfo2.setCitedArticles(new ArrayList<CitedArticle>()); articleInfo2.getCitedArticles().add(citedArticle2); return new Object[][] { { articleInfo1 }, { articleInfo2 } }; } @DataProvider(name = "articleAffiliations") public Object[][] getArticleAffiliations(){ String doi = "info:doi/10.1371/journal.pone.0048915"; Article a = new Article(doi); //add the asset record for the XML. The fileService needs this List<ArticleAsset> assetsForArticle1 = new LinkedList<ArticleAsset>(); ArticleAsset asset1ForArticle1 = new ArticleAsset(); asset1ForArticle1.setContentType("XML"); asset1ForArticle1.setContextElement("Fake ContextElement for asset1ForArticle1"); asset1ForArticle1.setDoi("info:doi/10.1371/journal.pone.0048915"); asset1ForArticle1.setExtension("XML"); asset1ForArticle1.setSize(1000001l); asset1ForArticle1.setCreated(new Date()); asset1ForArticle1.setLastModified(new Date()); assetsForArticle1.add(asset1ForArticle1); a.setAssets(assetsForArticle1); dummyDataStore.store(a); //LinkedHashMap for ordering Map<String, List<AuthorView>> affiliationSets = new LinkedHashMap<String, List<AuthorView>>() {{ //lots of affiliates and authors put("Department of Physiology (Animal Physiology II), Faculty of Biology, Universidad Complutense, Instituto de Investigación Sanitaria del Hospital Clínico San Carlos, Madrid, Spain", new ArrayList<AuthorView>() {{ add(AuthorView.builder() .setGivenNames("Virginia") .setSurnames("Mela") .build()); add(AuthorView.builder() .setGivenNames("Álvaro") .setSurnames("Llorente-Berzal") .build()); add(AuthorView.builder() .setGivenNames("María-Paz") .setSurnames("Viveros") .build()); }}); put("Department of Endocrinology, Hospital Infantil Universitario Niño Jesús, Instituto de Investigación Biomédica Princesa, Madrid, Spain", new ArrayList<AuthorView>(){{ add(AuthorView.builder() .setGivenNames("Francisca") .setSurnames("Díaz") .build()); add(AuthorView.builder() .setGivenNames("Jesús") .setSurnames("Argente") .build()); add(AuthorView.builder() .setGivenNames("Julie A.") .setSurnames("Chowen") .build()); }}); put("Department of Pediatrics, Universidad Autónoma de Madrid, Madrid, Spain", new ArrayList<AuthorView>(){{ add(AuthorView.builder() .setGivenNames("Jesús") .setSurnames("Argente") .build()); }}); put("CIBER de Fisiopatología de Obesidad y Nutrición, Instituto Carlos III, Madrid, Spain", new ArrayList<AuthorView>(){{ add(AuthorView.builder() .setGivenNames("Francisca") .setSurnames("Díaz") .build()); add(AuthorView.builder() .setGivenNames("Jesús") .setSurnames("Argente") .build()); add(AuthorView.builder() .setGivenNames("Julie A.") .setSurnames("Chowen") .build()); }}); }}; //TODO - cover following cases when time permits //same author shows up in multiple affiliates // info:doi/10.1371/journal.pmed.0020073 //affiliates without authors //10.1371/journal.pmed.0020073 return new Object[][]{{doi, affiliationSets}}; } /** * Make sure article affiliations are listed in order in which they appear in xml * * @param doi */ @Test(dataProvider = "articleAffiliations") public void testGetAffiliations(String doi, Map<String, List<AuthorView>> affiliationSets) throws Exception { String fsid = fileStoreService.objectIDMapper().doiTofsid(doi, "XML"); InputStream is = fileStoreService.getFileInStream(fsid); org.w3c.dom.Document doc = xmlService.createDocBuilder().parse(is); assertNotNull(doc, "Couldn't find " + doi); //perhaps a sub-optimal implementation of duo iteration, but otherwise it seems like a lot of boilerplate //for just a test Iterator testData = affiliationSets.entrySet().iterator(); for (Map.Entry<String, List<AuthorView>> mutEntry : fetchArticleService.getAuthorsByAffiliation(doc, fetchArticleService.getAuthors(doc)).entrySet()) { Map.Entry<String, List<AuthorView>> testDatum = (Map.Entry<String, List<AuthorView>>) testData.next(); assertEquals(mutEntry.getKey(),testDatum.getKey(), "Article affiliation names don't match"); Iterator testAuthors = testDatum.getValue().iterator(); for(AuthorView mutAuthor : mutEntry.getValue()){ AuthorView testAuthor = (AuthorView)testAuthors.next(); assertEquals(mutAuthor.getFullName(), testAuthor.getFullName(),"Author names don't match"); } //make sure we've covered all test data assertFalse(testAuthors.hasNext(),"Not all test authors accounted for"); } //make sure we've covered all test data assertFalse(testData.hasNext(), "Not all test affiliations accounted for"); } /** * This is testing the xsl transform of the article xml */ @Test(dataProvider = "articleInfos") public void testGetArticleAsHTML(ArticleInfo articleInfo) throws Exception { // note, addExtraCitationInfo function throws an error if the citations in the article xml doesn't match the // citedArticles list in the articleInfo object String output = fetchArticleService.getArticleAsHTML(articleInfo); Document doc = Jsoup.parseBodyFragment(output); // test all the different aspects of the xsl transformation for (HtmlChecker validator : HtmlChecker.values()) { validator.check(doc); } } @Test(dataProvider = "articlesForCorrespondingTest") public void testCorrespondingAuthors(ArticleInfo article, List<String> authors) throws Exception { String fsid = fileStoreService.objectIDMapper().doiTofsid(article.getDoi(), "XML"); InputStream fs = fileStoreService.getFileInStream(fsid); org.w3c.dom.Document dom = xmlService.createDocBuilder().parse(fs); List<String> results = fetchArticleService.getCorrespondingAuthors(dom); assertEquals(authors.size(), results.size(), "Differing count of authors"); assertEquals(results, authors); } @Test(dataProvider = "snippetsForCorrespondingTest") public void correspondingTest(String authorNode, String[] results) throws Exception { List<String> rs = FetchArticleServiceImpl.parseOutAuthorEmails(authorNode); assertEquals(rs.toArray(new String[rs.size()]), results); } @Test(dataProvider = "articlesWithDummyAffils") public void testGetAuthors(ArticleInfo article, List<AuthorView> testAuthors) throws Exception { String fsid = fileStoreService.objectIDMapper().doiTofsid(article.getDoi(), "XML"); InputStream fs = fileStoreService.getFileInStream(fsid); org.w3c.dom.Document dom = xmlService.createDocBuilder().parse(fs); assertNotNull(dom, "Problem loading documenty"); logger.info(article.getDoi()); List<AuthorView> authors = fetchArticleService.getAuthors(dom); assertTrue(authors.size() > 0, "No authors found"); assertTrue(testAuthors.size() > 0, "No test authors found"); assertEquals(testAuthors.size(), authors.size(), "Differing count of authors"); //For debugging: for(int a = 0; a < testAuthors.size(); a++) { logger.info("Test: " + a); printAuthor(testAuthors.get(a)); logger.info("Result: " + a); printAuthor(authors.get(a)); } assertEquals(testAuthors, authors); } /** * Data provider for article Eoc body * @return */ @DataProvider(name = "articlesWithEoc") public Object[][] getArticlesWithEoc() { //Test an article with Expression of concern ArticleInfo a1 = new ArticleInfo("info:doi/10.1371/journal.pone.0049703"); String eocTest = "\n" + " \n" + " \n" + " <p>After the publication of this article, a number of concerns were raised in relation to different " + "aspects of the research reported. The <italic>PLOS ONE</italic> editors carried out an evaluation of the " + "history of the manuscript, which revealed that due to a failure in the peer review process, several aspects " + "of the research were not adequately evaluated before publication.</p>\n" + " <p>As a result, the <italic>PLOS ONE</italic> editors have undertaken a thorough re-examination of " + "this study, involving both external and internal advisers. This assessment has revealed the following " + "concerns regarding the study:</p>\n" + " <ol class=\"alpha-lower\">\n" + " \n" + "<li>\n" + " <p>The description of the alleles in the article is inadequate.</p>\n" + " </li>\n" + " \n" + "<li>\n" + " <p>There are concerns over the study design employed to study the association; a single-gene " + "association study based on Cox-2 or a genome-wide association study have been recommended as more " + "appropriate approaches to study this association.</p>\n" + " </li>\n" + " \n" + "<li>\n" + " <p>The validity of the control population employed in the study is compromised as it " + "involved a different breed.</p>\n" + " </li>\n" + " \n" + "<li>\n" + " <p>There are concerns about the strength of the evidence shown to support an association " + "between the Cox-2 variant and the dogs' phenotypes, as the evidence from other breeds suggests that " + "this may be a neutral DNA variant.</p>\n" + " </li>\n" + " </ul>\n" + " <p>In the light of the concerns outlined above, the <italic>PLOS ONE</italic> editors are issuing " + "this Expression of Concern in order to make readers aware of the concerns about the reliability of the " + "results and conclusions reported in the article.</p>"; dummyDataStore.store(a1) ; return new Object[][] { {a1, eocTest} }; } /** * tests if the Eoc body is returned correctly or not * @param articleInfo * @param eocTest * @throws Exception */ @Test (dataProvider = "articlesWithEoc") public void testEoc(ArticleInfo articleInfo,String eocTest) throws Exception { String fsid = fileStoreService.objectIDMapper().doiTofsid(articleInfo.getDoi(), "XML"); InputStream fs = fileStoreService.getFileInStream(fsid); org.w3c.dom.Document dom = xmlService.createDocBuilder().parse(fs); String eoc = fetchArticleService.getAmendmentBody(dom); assertEquals(eocTest.trim(), eoc.trim(), "Expression of concerns didn't match"); } private void printAuthor(AuthorView av) { logger.info("---------------------------------"); logger.info("getFullName :" + av.getFullName()); logger.info("getGivenNames :" + av.getGivenNames()); logger.info("getSuffix :" + av.getSuffix()); logger.info("getSurnames :" + av.getSurnames()); logger.info("getCorresponding :" + av.getCorresponding()); logger.info("getOnBehalfOf :" + av.getOnBehalfOf()); logger.info("getDeceased :" + av.getDeceased()); logger.info("getRelatedFootnote :" + av.getRelatedFootnote()); logger.info("getEqualContrib :" + av.getEqualContrib()); for(String curAddress : av.getCurrentAddresses()) { logger.info("curAddress :" + curAddress); } for(String affil : av.getAffiliations()) { logger.info("affil :" + affil); } for(String note : av.getCustomFootnotes()) { logger.info("note :" + note); } logger.info("---------------------------------"); } }