diff --git a/.travis.yml b/.travis.yml index 993fc28171..99dc5da5ea 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,8 +29,6 @@ env: before_install: # Remove outdated settings.xml from Travis builds. Workaround for https://github.com/travis-ci/travis-ci/issues/4629 - - sed -i 's/^orcid\.clientid.*/orcid.clientid='$ORCID_CLIENTID'/g' dspace-api/src/test/data/dspaceFolder/config/local.cfg - - sed -i 's/^orcid\.clientsecret.*/orcid.clientsecret='$ORCID_CLIENTSECRET'/g' dspace-api/src/test/data/dspaceFolder/config/local.cfg - rm ~/.m2/settings.xml # Create two jobs to run Unit & Integration tests in parallel. # These jobs only differ in the TEST_FLAGS defined below, diff --git a/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java b/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java index 7a75d0600d..2a75b7cbd2 100644 --- a/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java +++ b/dspace-api/src/main/java/org/dspace/external/OrcidRestConnector.java @@ -7,7 +7,6 @@ */ package org.dspace.external; -import java.io.IOException; import java.io.InputStream; import java.util.Scanner; @@ -16,7 +15,6 @@ import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.util.EntityUtils; import org.apache.logging.log4j.Logger; /** @@ -56,14 +54,6 @@ public class OrcidRestConnector { result = getResponse.getEntity().getContent(); } catch (Exception e) { getGotError(e, fullPath); - } finally { - if (getResponse != null) { - try { - EntityUtils.consume(getResponse.getEntity()); - } catch (IOException e) { - throw new RuntimeException(e); - } - } } return result; diff --git a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java index 02a245d159..86b62cf98b 100644 --- a/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java +++ b/dspace-api/src/main/java/org/dspace/external/provider/impl/OrcidV3AuthorDataProvider.java @@ -17,7 +17,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; -import javax.annotation.PostConstruct; import org.apache.commons.lang3.StringUtils; import org.apache.http.HttpResponse; @@ -61,16 +60,15 @@ public class OrcidV3AuthorDataProvider implements ExternalDataProvider { public static final String ORCID_ID_SYNTAX = "\\d{4}-\\d{4}-\\d{4}-(\\d{3}X|\\d{4})"; - @PostConstruct - private void setup() { - this.converter = new XMLtoBio(); - } - @Override public String getSourceIdentifier() { return sourceIdentifier; } + public OrcidV3AuthorDataProvider() { + converter = new XMLtoBio(); + } + /** * Initialize the accessToken that is required for all subsequent calls to ORCID. * @@ -285,11 +283,4 @@ public class OrcidV3AuthorDataProvider implements ExternalDataProvider { this.orcidRestConnector = orcidRestConnector; } - public XMLtoBio getConverter() { - return converter; - } - - public void setConverter(XMLtoBio converter) { - this.converter = converter; - } } diff --git a/dspace-api/src/test/data/dspaceFolder/config/local.cfg b/dspace-api/src/test/data/dspaceFolder/config/local.cfg index fd7224bcd9..5f32bd0919 100644 --- a/dspace-api/src/test/data/dspaceFolder/config/local.cfg +++ b/dspace-api/src/test/data/dspaceFolder/config/local.cfg @@ -126,9 +126,6 @@ configuration.not.exposed = secret_value configuration.exposed.single.value = public_value configuration.exposed.array.value = public_value_1, public_value_2 -orcid.clientid = -orcid.clientsecret = - # Test config for the authentication ip functionality authentication-ip.Staff = 5.5.5.5 authentication-ip.Student = 6.6.6.6 diff --git a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidExternalSourcesIT.java b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidExternalSourcesIT.java index 0399b613bf..36656717a9 100644 --- a/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidExternalSourcesIT.java +++ b/dspace-server-webapp/src/test/java/org/dspace/app/rest/OrcidExternalSourcesIT.java @@ -14,19 +14,20 @@ import static org.springframework.test.web.servlet.request.MockMvcRequestBuilder import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; +import java.io.InputStream; + import org.apache.commons.lang3.StringUtils; import org.dspace.app.rest.test.AbstractControllerIntegrationTest; +import org.dspace.external.OrcidRestConnector; import org.dspace.external.provider.impl.OrcidV3AuthorDataProvider; -import org.dspace.external.provider.orcid.xml.XMLtoBio; import org.dspace.services.ConfigurationService; import org.hamcrest.Matchers; import org.junit.Assume; import org.junit.Test; import org.mockito.ArgumentMatchers; import org.mockito.Mockito; -import org.orcid.jaxb.model.record_v3.NameType; -import org.orcid.jaxb.model.record_v3.NameType.FamilyName; -import org.orcid.jaxb.model.record_v3.Person; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; import org.springframework.beans.factory.annotation.Autowired; /** @@ -52,7 +53,6 @@ public class OrcidExternalSourcesIT extends AbstractControllerIntegrationTest { @Test public void findOneExternalSourcesExistingSources() throws Exception { - onlyRunIfConfigExists(); getClient().perform(get("/api/integration/externalsources/orcid")) .andExpect(status().isOk()) .andExpect(jsonPath("$", Matchers.allOf( @@ -65,6 +65,7 @@ public class OrcidExternalSourcesIT extends AbstractControllerIntegrationTest { @Test public void findOneExternalSourcesExistingSourcesWithentryValueTest() throws Exception { + // this test will query the real ORCID API if configured in the CI otherwise will be skipped onlyRunIfConfigExists(); String entry = "0000-0002-9029-1854"; getClient().perform(get("/api/integration/externalsources/orcid/entryValues/" + entry)) @@ -83,7 +84,8 @@ public class OrcidExternalSourcesIT extends AbstractControllerIntegrationTest { } @Test - public void findOneExternalSourceEntriesApplicableQuery() throws Exception { + public void findOneExternalSourceEntriesApplicableQueryTest() throws Exception { + // this test will query the real ORCID API if configured in the CI otherwise will be skipped onlyRunIfConfigExists(); String q = "orcid:0000-0002-9029-1854"; getClient().perform(get("/api/integration/externalsources/orcid/entries") @@ -108,17 +110,19 @@ public class OrcidExternalSourcesIT extends AbstractControllerIntegrationTest { @Test public void findOneExternalSourceEntriesApplicableQueryFamilyNameAndGivenNamesTest() throws Exception { + // this test will query the real ORCID API if configured in the CI otherwise will be skipped onlyRunIfConfigExists(); String q = "family-name:bollini AND given-names:andrea"; getClient().perform(get("/api/integration/externalsources/orcid/entries") .param("query", q)) .andExpect(status().isOk()) - .andExpect(jsonPath("$._embedded.externalSourceEntries[0]", Matchers.allOf( - hasJsonPath("$.id", is("0000-0002-9029-1854")), - hasJsonPath("$.display", is("Bollini, Andrea")), - hasJsonPath("$.value", is("Bollini, Andrea")), - hasJsonPath("$.externalSource", is("orcid")), - hasJsonPath("$.type", is("externalSourceEntry")) + .andExpect(jsonPath("$._embedded.externalSourceEntries", Matchers.hasItem( + Matchers.allOf( + hasJsonPath("$.id", is("0000-0002-9029-1854")), + hasJsonPath("$.display", is("Bollini, Andrea")), + hasJsonPath("$.value", is("Bollini, Andrea")), + hasJsonPath("$.externalSource", is("orcid")), + hasJsonPath("$.type", is("externalSourceEntry"))) ))) .andExpect(jsonPath("$._embedded.externalSourceEntries[0].metadata['dc.identifier.uri'][0].value", is("https://orcid.org/0000-0002-9029-1854"))) @@ -132,21 +136,17 @@ public class OrcidExternalSourcesIT extends AbstractControllerIntegrationTest { @Test public void findOneExternalSourcesMockitoTest() throws Exception { - - XMLtoBio converter = Mockito.mock(XMLtoBio.class); - orcidV3AuthorDataProvider.setConverter(converter); + OrcidRestConnector orcidConnector = Mockito.mock(OrcidRestConnector.class); + OrcidRestConnector realConnector = orcidV3AuthorDataProvider.getOrcidRestConnector(); + orcidV3AuthorDataProvider.setOrcidRestConnector(orcidConnector); + when(orcidConnector.get(ArgumentMatchers.endsWith("/person"), ArgumentMatchers.any())) + .thenAnswer(new Answer() { + public InputStream answer(InvocationOnMock invocation) { + return getClass().getResourceAsStream("orcid-person-record.xml"); + } + }); String entry = "0000-0002-9029-1854"; - - NameType name = new NameType(); - name.setFamilyName(new FamilyName("Bollini, Andrea")); - - Person person = new Person(); - person.setName(name); - name.setPath(entry); - - when(converter.convertSinglePerson(ArgumentMatchers.any())).thenReturn(person); - getClient().perform(get("/api/integration/externalsources/orcid/entryValues/" + entry)) .andExpect(status().isOk()) .andExpect(jsonPath("$", Matchers.allOf( @@ -157,6 +157,94 @@ public class OrcidExternalSourcesIT extends AbstractControllerIntegrationTest { hasJsonPath("$.type", is("externalSourceEntry")) ))); - orcidV3AuthorDataProvider.setConverter(new XMLtoBio()); + orcidV3AuthorDataProvider.setOrcidRestConnector(realConnector); } + + @Test + public void findOneExternalSourceEntriesApplicableQueryMockitoTest() throws Exception { + OrcidRestConnector orcidConnector = Mockito.mock(OrcidRestConnector.class); + OrcidRestConnector realConnector = orcidV3AuthorDataProvider.getOrcidRestConnector(); + orcidV3AuthorDataProvider.setOrcidRestConnector(orcidConnector); + try { + when(orcidConnector.get(ArgumentMatchers.startsWith("search?"), ArgumentMatchers.any())) + .thenAnswer(new Answer() { + public InputStream answer(InvocationOnMock invocation) { + return getClass().getResourceAsStream("orcid-search.xml"); + } + }); + when(orcidConnector.get(ArgumentMatchers.endsWith("/person"), ArgumentMatchers.any())) + .thenAnswer(new Answer() { + public InputStream answer(InvocationOnMock invocation) { + return getClass().getResourceAsStream("orcid-person-record.xml"); + } + }); + String q = "orcid:0000-0002-9029-1854"; + getClient().perform(get("/api/integration/externalsources/orcid/entries") + .param("query", q)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$._embedded.externalSourceEntries[0]", Matchers.allOf( + hasJsonPath("$.id", is("0000-0002-9029-1854")), + hasJsonPath("$.display", is("Bollini, Andrea")), + hasJsonPath("$.value", is("Bollini, Andrea")), + hasJsonPath("$.externalSource", is("orcid")), + hasJsonPath("$.type", is("externalSourceEntry")) + ))) + .andExpect(jsonPath("$._embedded.externalSourceEntries[0].metadata['dc.identifier.uri'][0].value", + is("https://orcid.org/0000-0002-9029-1854"))) + .andExpect(jsonPath("$._embedded.externalSourceEntries[0].metadata['person.familyName'][0].value", + is("Bollini"))) + .andExpect(jsonPath("$._embedded.externalSourceEntries[0].metadata['person.givenName'][0].value", + is("Andrea"))) + .andExpect(jsonPath( + "$._embedded.externalSourceEntries[0].metadata['person.identifier.orcid'][0].value", + is("0000-0002-9029-1854"))); + } finally { + orcidV3AuthorDataProvider.setOrcidRestConnector(realConnector); + } + } + + @Test + public void findOneExternalSourceEntriesApplicableQueryFamilyNameAndGivenNamesMockitoTest() throws Exception { + OrcidRestConnector orcidConnector = Mockito.mock(OrcidRestConnector.class); + OrcidRestConnector realConnector = orcidV3AuthorDataProvider.getOrcidRestConnector(); + orcidV3AuthorDataProvider.setOrcidRestConnector(orcidConnector); + try { + when(orcidConnector.get(ArgumentMatchers.startsWith("search?"), ArgumentMatchers.any())) + .thenAnswer(new Answer() { + public InputStream answer(InvocationOnMock invocation) { + return getClass().getResourceAsStream("orcid-search.xml"); + } + }); + when(orcidConnector.get(ArgumentMatchers.endsWith("/person"), ArgumentMatchers.any())) + .thenAnswer(new Answer() { + public InputStream answer(InvocationOnMock invocation) { + return getClass().getResourceAsStream("orcid-person-record.xml"); + } + }); + String q = "family-name:bollini AND given-names:andrea"; + getClient().perform(get("/api/integration/externalsources/orcid/entries") + .param("query", q)) + .andExpect(status().isOk()) + .andExpect(jsonPath("$._embedded.externalSourceEntries", Matchers.hasItem( + Matchers.allOf( + hasJsonPath("$.id", is("0000-0002-9029-1854")), + hasJsonPath("$.display", is("Bollini, Andrea")), + hasJsonPath("$.value", is("Bollini, Andrea")), + hasJsonPath("$.externalSource", is("orcid")), + hasJsonPath("$.type", is("externalSourceEntry"))) + ))) + .andExpect(jsonPath("$._embedded.externalSourceEntries[0].metadata['dc.identifier.uri'][0].value", + is("https://orcid.org/0000-0002-9029-1854"))) + .andExpect(jsonPath("$._embedded.externalSourceEntries[0].metadata['person.familyName'][0].value", + is("Bollini"))) + .andExpect(jsonPath("$._embedded.externalSourceEntries[0].metadata['person.givenName'][0].value", + is("Andrea"))) + .andExpect(jsonPath( + "$._embedded.externalSourceEntries[0].metadata['person.identifier.orcid'][0].value", + is("0000-0002-9029-1854"))); + } finally { + orcidV3AuthorDataProvider.setOrcidRestConnector(realConnector); + } + } + } diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/orcid-person-record.xml b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/orcid-person-record.xml new file mode 100644 index 0000000000..ed51b8e50d --- /dev/null +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/orcid-person-record.xml @@ -0,0 +1,234 @@ + + + 2018-02-05T23:27:36.636Z + + 2016-04-15T23:17:03.663Z + 2016-04-15T23:17:03.663Z + Andrea + Bollini + + + + 2017-07-18T15:10:48.940Z + + 2017-01-16T08:12:12.946Z + 2017-07-18T15:10:48.940Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + Linkedin + https://it.linkedin.com/in/andreabollini + + + 2014-11-06T10:37:30.383Z + 2017-07-18T15:10:48.940Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + 4Science + http://www.4science.it/en/ + + + 2014-11-06T10:37:30.412Z + 2017-07-18T15:10:48.940Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + DSpace + http://www.dspace.org + + + 2014-11-06T10:37:30.398Z + 2017-07-18T15:10:48.940Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + DSpace-CRIS + https://wiki.duraspace.org/display/DSPACECRIS + + + + 2016-09-12T11:22:47.354Z + + 2016-09-12T10:45:26.123Z + 2016-09-12T11:22:47.354Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + andrea.bollini@4science.it + + + + 2016-06-06T15:29:36.952Z + + 2016-01-24T18:24:26.704Z + 2016-06-06T15:29:36.952Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + IT + + + + 2016-03-01T11:03:22.508Z + + 2013-05-30T10:55:45.614Z + 2016-03-01T11:03:22.508Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + Software + + + 2013-05-30T10:55:45.614Z + 2016-03-01T11:03:22.508Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + Open Source + + + 2013-05-30T10:55:45.614Z + 2016-03-01T11:03:22.508Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + JAVA + + + 2016-03-01T11:03:22.491Z + 2016-03-01T11:03:22.491Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + CERIF + + + 2016-03-01T11:03:22.502Z + 2016-03-01T11:03:22.502Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + CRIS + + + 2016-03-01T11:03:22.503Z + 2016-03-01T11:03:22.503Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + RIMS + + + 2016-03-01T11:03:22.504Z + 2016-03-01T11:03:22.504Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + Open Standards + + + 2016-03-01T11:03:22.505Z + 2016-03-01T11:03:22.505Z + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + OAI-PMH + + + + 2018-02-05T23:27:36.636Z + + 2013-05-30T10:55:45.614Z + 2018-02-05T23:27:36.636Z + + + https://orcid.org/client/0000-0002-5982-8983 + 0000-0002-5982-8983 + orcid.org + + Scopus - Elsevier + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + Andrea Bollini + + Scopus Author ID + 55484808800 + http://www.scopus.com/inward/authorDetails.url?authorID=55484808800&partnerID=MN8TOARS + self + + + \ No newline at end of file diff --git a/dspace-server-webapp/src/test/resources/org/dspace/app/rest/orcid-search.xml b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/orcid-search.xml new file mode 100644 index 0000000000..3f7fe9a284 --- /dev/null +++ b/dspace-server-webapp/src/test/resources/org/dspace/app/rest/orcid-search.xml @@ -0,0 +1,10 @@ + + + + + https://orcid.org/0000-0002-9029-1854 + 0000-0002-9029-1854 + orcid.org + + + \ No newline at end of file diff --git a/dspace/config/dspace.cfg b/dspace/config/dspace.cfg index f31fea7d64..030d09dbd7 100644 --- a/dspace/config/dspace.cfg +++ b/dspace/config/dspace.cfg @@ -1478,6 +1478,8 @@ orcid.api.url = https://pub.orcid.org/v3.0 orcid.url = https://orcid.org/ # ORCID Credentials +# Your public or member API Credentials, see +# https://orcid.org/content/register-client-application-0 orcid.clientid = orcid.clientsecret =