diff --git a/mycore-orcid2/src/main/java/org/mycore/orcid2/util/MCRIdentifier.java b/mycore-base/src/main/java/org/mycore/datamodel/legalentity/MCRIdentifier.java similarity index 98% rename from mycore-orcid2/src/main/java/org/mycore/orcid2/util/MCRIdentifier.java rename to mycore-base/src/main/java/org/mycore/datamodel/legalentity/MCRIdentifier.java index 10eca0f8ce..715eb8513e 100644 --- a/mycore-orcid2/src/main/java/org/mycore/orcid2/util/MCRIdentifier.java +++ b/mycore-base/src/main/java/org/mycore/datamodel/legalentity/MCRIdentifier.java @@ -16,7 +16,7 @@ * along with MyCoRe. If not, see . */ -package org.mycore.orcid2.util; +package org.mycore.datamodel.legalentity; import java.util.Locale; import java.util.Objects; diff --git a/mycore-base/src/main/java/org/mycore/datamodel/legalentity/MCRLegalEntityService.java b/mycore-base/src/main/java/org/mycore/datamodel/legalentity/MCRLegalEntityService.java new file mode 100644 index 0000000000..f1ba5a2372 --- /dev/null +++ b/mycore-base/src/main/java/org/mycore/datamodel/legalentity/MCRLegalEntityService.java @@ -0,0 +1,53 @@ +/* + * This file is part of *** M y C o R e *** + * See https://www.mycore.de/ for details. + * + * MyCoRe is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MyCoRe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MyCoRe. If not, see . + */ + +package org.mycore.datamodel.legalentity; + +import java.util.Set; + +/** + * Services that implement this interface should search for all identifiers of a specific legal entity (e.g. a person) + * using a specific, identifying {@link MCRIdentifier}, or add an identifier to the legal entity. The identifier + * can be any key-value pair that can uniquely identify a legal entity. The interface is intentionally generic to allow + * different identifier schemes and lookup implementations. + */ +public interface MCRLegalEntityService { + + /** + * Gets all identifiers of a legal entity determined by a specific identifier. + * @param identifier unique identifier of legal entity, not null + * @return a set of identifiers a legal entity owns + */ + Set getAllIdentifiers(MCRIdentifier identifier); + + /** + * Gets a legal entity's identifiers of a given type. The legal entity is determined by a specific identifier. + * @param primaryIdentifier unique identifier of legal entity, not null + * @param identifierType the type of looked up identifiers as a string, not null + * @return a set of identifiers a legal entity owns + */ + Set getTypedIdentifiers(MCRIdentifier primaryIdentifier, String identifierType); + + /** + * Adds an identifier to a legal entity. The entity is determined by a specific, given identifier + * @param primaryIdentifier unique identifier of legal entity, not null + * @param identifierToAdd the identifier to add, not null + */ + void addIdentifier(MCRIdentifier primaryIdentifier, MCRIdentifier identifierToAdd); + +} diff --git a/mycore-mods/pom.xml b/mycore-mods/pom.xml index 6991bc5f15..998a88e427 100644 --- a/mycore-mods/pom.xml +++ b/mycore-mods/pom.xml @@ -128,6 +128,10 @@ org.mycore mycore-solr + + org.mycore + mycore-user2 + xalan xalan diff --git a/mycore-mods/src/main/java/org/mycore/mods/MCRUser2MODSPersonIdentifierService.java b/mycore-mods/src/main/java/org/mycore/mods/MCRUser2MODSPersonIdentifierService.java new file mode 100644 index 0000000000..2f04c0d138 --- /dev/null +++ b/mycore-mods/src/main/java/org/mycore/mods/MCRUser2MODSPersonIdentifierService.java @@ -0,0 +1,164 @@ +/* + * This file is part of *** M y C o R e *** + * See https://www.mycore.de/ for details. + * + * MyCoRe is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MyCoRe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MyCoRe. If not, see . + */ + +package org.mycore.mods; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jdom2.Element; +import org.mycore.access.MCRAccessException; +import org.mycore.common.MCRConstants; +import org.mycore.common.MCRPersistenceException; +import org.mycore.datamodel.legalentity.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRLegalEntityService; +import org.mycore.datamodel.metadata.MCRMetadataManager; +import org.mycore.datamodel.metadata.MCRObject; +import org.mycore.datamodel.metadata.MCRObjectID; +import org.mycore.user2.MCRUser; +import org.mycore.user2.MCRUserManager; + +import java.util.Collections; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +public class MCRUser2MODSPersonIdentifierService implements MCRLegalEntityService { + + private static final Logger LOGGER = LogManager.getLogger(); + + public static final String MODSPERSON_ATTR_NAME = "id_modsperson"; + + public static final String USERID = "userid"; + + public static final String MODS_NAME = "name"; + + public static final String MODS_NAMEIDENTIFIER = "nameIdentifier"; + + public static final String TYPE = "type"; + + + /** + * Gets all {@link MCRIdentifier MCRIdentifiers} of a modsperson by reference to a {@link org.mycore.user2.MCRUser} + * and its modsperson id. + * @param userId the user id connected to the modsperson + * @return all known identifiers or an empty set + */ + @Override + public Set getAllIdentifiers(MCRIdentifier userId) { + return getIdentifiers(userId, null); + } + + /** + * Gets a modsperson's {@link MCRIdentifier MCRIdentifiers} of a specified type by reference + * to a {@link org.mycore.user2.MCRUser} and its modsperson id. + * @param userId the user id connected to the modsperson + * @param identifierType the type of identifier to filter for + * @return all known identifiers of a specified type or an empty set + */ + @Override + public Set getTypedIdentifiers(MCRIdentifier userId, String identifierType) { + return getIdentifiers(userId, identifierType); + } + + /** + * Adds a {@link MCRIdentifier MCRIdentifiers} to a modsperson by reference to a {@link org.mycore.user2.MCRUser} + * and its modsperson id. + * @param userId the user id connected to the modsperson + * @param attributeToAdd the nameIdentifier to add to the modsperson + */ + @Override + public void addIdentifier(MCRIdentifier userId, MCRIdentifier attributeToAdd) { + Optional modspersonOptional = findModspersonByUsername(userId); + if (modspersonOptional.isEmpty()) { + return; + } + MCRMODSWrapper wrapper = new MCRMODSWrapper(modspersonOptional.get()); + Element modsName = wrapper.getMODS().getChild(MODS_NAME, MCRConstants.MODS_NAMESPACE); + if (modsName == null) { + return; + } + Element nameIdentifier = new Element(MODS_NAMEIDENTIFIER, MCRConstants.MODS_NAMESPACE) + .setAttribute(TYPE, attributeToAdd.getType()) + .setText(attributeToAdd.getValue()); + modsName.addContent(nameIdentifier); + try { + MCRMetadataManager.update(modspersonOptional.get()); + } catch (MCRAccessException | MCRPersistenceException e) { + if (LOGGER.isWarnEnabled()) { + LOGGER.warn("Could not update modsperson object for user id {}", + userId.getValue(), e); + } + } + } + + /** + * helper method to search for identifiers in a modsperson by a user-ID + * @param userId the user id connected to the modsperson + * @param identifierType optional type filter, leave null for no filter + * @return a set of all identifiers found + */ + private Set getIdentifiers(MCRIdentifier userId, String identifierType) { + Optional modspersonOptional = findModspersonByUsername(userId); + if (modspersonOptional.isEmpty()) { + return Collections.emptySet(); + } + MCRMODSWrapper wrapper = new MCRMODSWrapper(modspersonOptional.get()); + Element modsName = wrapper.getMODS().getChild(MODS_NAME, MCRConstants.MODS_NAMESPACE); + if (modsName == null) { + return Collections.emptySet(); + } + if (identifierType != null) { + return modsName.getChildren(MODS_NAMEIDENTIFIER, MCRConstants.MODS_NAMESPACE) + .stream().filter(e -> identifierType.equals(e.getAttributeValue(TYPE))) + .map(e -> new MCRIdentifier(e.getAttributeValue(TYPE), e.getText())) + .collect(Collectors.toSet()); + } + return modsName.getChildren(MODS_NAMEIDENTIFIER, MCRConstants.MODS_NAMESPACE) + .stream().map(e -> new MCRIdentifier(e.getAttributeValue(TYPE), e.getText())) + .collect(Collectors.toSet()); + } + + /** + * Takes a username and returns an Optional with the referenced modsperson. + * @param userId the user id + * @return a nullable Optional that might contain a modsperson + */ + private Optional findModspersonByUsername(MCRIdentifier userId) { + if (userId == null || !USERID.equals(userId.getType())) { + return Optional.empty(); + } + MCRUser user = MCRUserManager.getUser(userId.getValue()); + if (user == null) { + return Optional.empty(); + } + String modspersonId = user.getUserAttribute(MODSPERSON_ATTR_NAME); + if (modspersonId == null) { + return Optional.empty(); + } + try { + MCRObject modsperson = MCRMetadataManager.retrieveMCRObject(MCRObjectID.getInstance(modspersonId)); + return Optional.of(modsperson); + } catch (MCRPersistenceException e) { + if (LOGGER.isWarnEnabled()) { + LOGGER.warn("Could not retrieve modsperson object for user id {} (modspersonId={})", + userId.getValue(), modspersonId, e); + } + return Optional.empty(); + } + } +} diff --git a/mycore-mods/src/test/java/org/mycore/mods/MCRUser2MODSPersonIdentifierServiceTest.java b/mycore-mods/src/test/java/org/mycore/mods/MCRUser2MODSPersonIdentifierServiceTest.java new file mode 100644 index 0000000000..1f004a47aa --- /dev/null +++ b/mycore-mods/src/test/java/org/mycore/mods/MCRUser2MODSPersonIdentifierServiceTest.java @@ -0,0 +1,171 @@ +/* + * This file is part of *** M y C o R e *** + * See https://www.mycore.de/ for details. + * + * MyCoRe is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MyCoRe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MyCoRe. If not, see . + */ + +package org.mycore.mods; + +import org.jdom2.Document; +import org.jdom2.JDOMException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mycore.access.MCRAccessBaseImpl; +import org.mycore.access.MCRAccessException; +import org.mycore.common.MCRTestConfiguration; +import org.mycore.common.MCRTestProperty; +import org.mycore.common.content.MCRURLContent; +import org.mycore.datamodel.legalentity.MCRIdentifier; +import org.mycore.datamodel.metadata.MCRMetadataManager; +import org.mycore.datamodel.metadata.MCRObject; +import org.mycore.datamodel.metadata.MCRObjectMetadataTest; +import org.mycore.test.MCRJPAExtension; +import org.mycore.test.MCRMetadataExtension; +import org.mycore.test.MyCoReTest; +import org.mycore.user2.MCRUser; +import org.mycore.user2.MCRUserManager; + +import java.io.IOException; +import java.net.URL; +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@MyCoReTest +@ExtendWith({ MCRJPAExtension.class, MCRMetadataExtension.class }) +@MCRTestConfiguration(properties = { + @MCRTestProperty(key = "MCR.Metadata.Type.modsperson", string = "true"), + @MCRTestProperty(key = "MCR.MODS.Types", string = "mods,modsperson"), + @MCRTestProperty(key = "MCR.MODS.NewObjectType", string = "mods"), + @MCRTestProperty(key = "MCR.Access.Class", classNameOf = MCRAccessBaseImpl.class) +}) +public class MCRUser2MODSPersonIdentifierServiceTest { + + private static final String ORCID_1 = "0000-0001-2345-6789"; + + private static final String ORCID_2 = "0000-0002-3456-7895"; + + private static final String ORCID_3 = "0000-0003-4567-8985"; + + private static final String SCOPUS = "87654321"; + + MCRUser2MODSPersonIdentifierService service; + + MCRUser user; + + @BeforeEach + public void setUp() throws Exception { + URL url1 = MCRObjectMetadataTest.class.getResource( + "/MCRUser2MODSPersonIdentifierServiceTest/junit_modsperson_00000001.xml"); + Document doc1 = new MCRURLContent(url1).asXML(); + MCRObject obj1 = new MCRObject(doc1); + MCRMetadataManager.create(obj1); + + user = new MCRUser("john"); + user.setRealName("John Doe"); + user.setUserAttribute("id_modsperson", "junit_modsperson_00000001"); + MCRUserManager.createUser(user); + + service = new MCRUser2MODSPersonIdentifierService(); + } + + @Test + public final void testGetAllIdentifiers() { + Set allIdentifiers = service.getAllIdentifiers( + new MCRIdentifier("userid", user.getUserID())); + Set expected = Set.of(new MCRIdentifier("orcid", ORCID_1), + new MCRIdentifier("orcid", ORCID_2), + new MCRIdentifier("orcid", ORCID_3), + new MCRIdentifier("scopus", SCOPUS), + new MCRIdentifier("something", "abcd")); + assertEquals(expected, allIdentifiers); + } + + @Test + public final void testGetTypedIdentifiers() { + final MCRIdentifier userid = new MCRIdentifier("userid", user.getUserID()); + Set typedIdentifiers = service.getTypedIdentifiers(userid,"orcid"); + Set expected = Set.of(new MCRIdentifier("orcid", ORCID_1), + new MCRIdentifier("orcid", ORCID_2), + new MCRIdentifier("orcid", ORCID_3)); + assertEquals(expected, typedIdentifiers); + + typedIdentifiers = service.getTypedIdentifiers(userid,"id_orcid"); + assertEquals(0, typedIdentifiers.size()); + + typedIdentifiers = service.getTypedIdentifiers( + new MCRIdentifier("userid", user.getUserID()),"scopus"); + assertEquals(Set.of(new MCRIdentifier("scopus", SCOPUS)), typedIdentifiers); + + typedIdentifiers = service.getTypedIdentifiers(userid, "something"); + assertEquals(Set.of(new MCRIdentifier("something", "abcd")), typedIdentifiers); + } + + @Test + public final void testAddIdentifier() throws MCRAccessException, IOException, JDOMException { + URL url2 = MCRObjectMetadataTest.class.getResource( + "/MCRUser2MODSPersonIdentifierServiceTest/junit_modsperson_00000002.xml"); + Document doc2 = new MCRURLContent(url2).asXML(); + MCRObject obj2 = new MCRObject(doc2); + MCRMetadataManager.create(obj2); + + MCRUser user2 = new MCRUser("jane"); + user2.setRealName("Jane Doe"); + user2.setUserAttribute("id_modsperson", "junit_modsperson_00000002"); + MCRUserManager.createUser(user2); + + final MCRIdentifier userid = new MCRIdentifier("userid", user2.getUserID()); + Set allIdentifiers = service.getAllIdentifiers(userid); + assertEquals(2, allIdentifiers.size()); + + service.addIdentifier(userid, new MCRIdentifier("orcid", ORCID_1)); // don't add id twice + allIdentifiers = service.getAllIdentifiers(userid); + assertEquals(2, allIdentifiers.size()); + + service.addIdentifier(userid, new MCRIdentifier("orcid", ORCID_3)); + allIdentifiers = service.getAllIdentifiers(userid); + assertEquals(3, allIdentifiers.size()); + Set expected = Set.of(new MCRIdentifier("orcid", ORCID_1), + new MCRIdentifier("orcid", ORCID_2), + new MCRIdentifier("orcid", ORCID_3)); + assertEquals(expected, allIdentifiers); + } + + @Test + public final void testAddIdentifierNoModsperson() { + Set allIdentifiers = service.getAllIdentifiers(new MCRIdentifier("userid", "noname")); + assertEquals(0, allIdentifiers.size()); + + MCRUser user3 = new MCRUser("james"); + user3.setRealName("James Doe"); + user3.setUserAttribute("id_orcid", ORCID_1); + MCRUserManager.createUser(user3); + + final MCRIdentifier userid = new MCRIdentifier("userid", user3.getUserID()); + allIdentifiers = service.getAllIdentifiers(userid); + assertEquals(0, allIdentifiers.size()); + + service.addIdentifier(userid, new MCRIdentifier("orcid", ORCID_2)); + allIdentifiers = service.getAllIdentifiers(userid); + assertEquals(0, allIdentifiers.size()); + + user3.setUserAttribute("id_modsperson", "junit_modsperson_00000404"); + MCRUserManager.updateUser(user3); + allIdentifiers = service.getAllIdentifiers(userid); + assertEquals(0, allIdentifiers.size()); + } + +} diff --git a/mycore-mods/src/test/resources/MCRUser2MODSPersonIdentifierServiceTest/junit_modsperson_00000001.xml b/mycore-mods/src/test/resources/MCRUser2MODSPersonIdentifierServiceTest/junit_modsperson_00000001.xml new file mode 100644 index 0000000000..f869f526e3 --- /dev/null +++ b/mycore-mods/src/test/resources/MCRUser2MODSPersonIdentifierServiceTest/junit_modsperson_00000001.xml @@ -0,0 +1,20 @@ + + + + + + + + Doe + John + 0000-0001-2345-6789 + 0000-0002-3456-7895 + 0000-0003-4567-8985 + 87654321 + abcd + + + + + + diff --git a/mycore-mods/src/test/resources/MCRUser2MODSPersonIdentifierServiceTest/junit_modsperson_00000002.xml b/mycore-mods/src/test/resources/MCRUser2MODSPersonIdentifierServiceTest/junit_modsperson_00000002.xml new file mode 100644 index 0000000000..0b69303795 --- /dev/null +++ b/mycore-mods/src/test/resources/MCRUser2MODSPersonIdentifierServiceTest/junit_modsperson_00000002.xml @@ -0,0 +1,17 @@ + + + + + + + + Doe + Jane + 0000-0001-2345-6789 + 0000-0002-3456-7895 + + + + + + diff --git a/mycore-orcid2/src/main/java/org/mycore/orcid2/MCRORCIDUtils.java b/mycore-orcid2/src/main/java/org/mycore/orcid2/MCRORCIDUtils.java index 6112c5788e..45f4138ecf 100644 --- a/mycore-orcid2/src/main/java/org/mycore/orcid2/MCRORCIDUtils.java +++ b/mycore-orcid2/src/main/java/org/mycore/orcid2/MCRORCIDUtils.java @@ -41,7 +41,7 @@ import org.mycore.datamodel.metadata.MCRObject; import org.mycore.mods.MCRMODSWrapper; import org.mycore.orcid2.exception.MCRORCIDException; -import org.mycore.orcid2.util.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRIdentifier; /** * Provides utility methods. diff --git a/mycore-orcid2/src/main/java/org/mycore/orcid2/user/MCRORCIDUser.java b/mycore-orcid2/src/main/java/org/mycore/orcid2/user/MCRORCIDUser.java index 5bfaadb435..0230ced097 100644 --- a/mycore-orcid2/src/main/java/org/mycore/orcid2/user/MCRORCIDUser.java +++ b/mycore-orcid2/src/main/java/org/mycore/orcid2/user/MCRORCIDUser.java @@ -28,10 +28,11 @@ import java.util.stream.Collectors; import org.mycore.common.config.MCRConfiguration2; +import org.mycore.datamodel.legalentity.MCRLegalEntityService; import org.mycore.orcid2.MCRORCIDConstants; import org.mycore.orcid2.client.MCRORCIDCredential; import org.mycore.orcid2.exception.MCRORCIDException; -import org.mycore.orcid2.util.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRIdentifier; import org.mycore.orcid2.util.MCRORCIDJSONMapper; import org.mycore.orcid2.validation.MCRORCIDValidationHelper; import org.mycore.user2.MCRUser; @@ -72,6 +73,8 @@ public class MCRORCIDUser { private final MCRUser user; + private final MCRLegalEntityService legalEntityService; + /** * Wraps MCRUser to MCRORCIDUser. * @@ -79,6 +82,19 @@ public class MCRORCIDUser { */ public MCRORCIDUser(MCRUser user) { this.user = user; + legalEntityService = MCRConfiguration2.getInstanceOfOrThrow( + MCRLegalEntityService.class, MCRORCIDConstants.CONFIG_PREFIX + "LegalEntityService.Class"); + } + + /** + * Wraps MCRUser to MCRORCIDUser. + * + * @param user the MCRUser + * @param legalEntityService the {@link MCRLegalEntityService} to use + */ + protected MCRORCIDUser(MCRUser user, MCRLegalEntityService legalEntityService) { + this.user = user; + this.legalEntityService = legalEntityService; } /** @@ -100,11 +116,10 @@ public void addORCID(String orcid) { if (!MCRORCIDValidationHelper.validateORCID(orcid)) { throw new MCRORCIDException("Invalid ORCID iD"); } - final MCRUserAttribute attribute = new MCRUserAttribute(ATTR_ORCID_ID, orcid); - // allow more than one ORCID iD per user - if (!user.getAttributes().contains(attribute)) { - user.getAttributes().add(new MCRUserAttribute(ATTR_ORCID_ID, orcid)); - } + final MCRIdentifier newOrcid = new MCRIdentifier("orcid", orcid); + final MCRIdentifier userid = new MCRIdentifier("userid", user.getUserID()); + + legalEntityService.addIdentifier(userid, newOrcid); } /** Returns user's ORCID iDs. @@ -112,9 +127,10 @@ public void addORCID(String orcid) { * @return ORCID iDs as set */ public Set getORCIDs() { - return user.getAttributes().stream() - .filter(a -> Objects.equals(a.getName(), ATTR_ORCID_ID)) - .map(MCRUserAttribute::getValue).collect(Collectors.toSet()); + final MCRIdentifier userid = new MCRIdentifier("userid", user.getUserID()); + Set orcidIdentifiers = legalEntityService.getTypedIdentifiers(userid, "orcid"); + return orcidIdentifiers.stream().map(MCRIdentifier::getValue) + .collect(Collectors.toSet()); } /** @@ -232,9 +248,8 @@ public MCRORCIDCredential getCredentialByORCID(String orcid) { * @return Set of MCRIdentifier */ public Set getIdentifiers() { - return user.getAttributes().stream().filter(a -> a.getName().startsWith(ATTR_ID_PREFIX)) - .map(a -> new MCRIdentifier(a.getName().substring(ATTR_ID_PREFIX.length()), a.getValue())) - .collect(Collectors.toSet()); + final MCRIdentifier userId = new MCRIdentifier("userid", user.getUserID()); + return legalEntityService.getAllIdentifiers(userId); } /** diff --git a/mycore-orcid2/src/main/java/org/mycore/orcid2/user/MCRORCIDUserUtils.java b/mycore-orcid2/src/main/java/org/mycore/orcid2/user/MCRORCIDUserUtils.java index 569fee157f..eed43d8305 100644 --- a/mycore-orcid2/src/main/java/org/mycore/orcid2/user/MCRORCIDUserUtils.java +++ b/mycore-orcid2/src/main/java/org/mycore/orcid2/user/MCRORCIDUserUtils.java @@ -30,7 +30,7 @@ import org.mycore.orcid2.client.exception.MCRORCIDRequestException; import org.mycore.orcid2.exception.MCRORCIDException; import org.mycore.orcid2.oauth.MCRORCIDOAuthClient; -import org.mycore.orcid2.util.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRIdentifier; import org.mycore.user2.MCRUser; import org.mycore.user2.MCRUserManager; diff --git a/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/rest/resources/MCRORCIDObjectResource.java b/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/rest/resources/MCRORCIDObjectResource.java index 3919ae7618..fda5a15036 100644 --- a/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/rest/resources/MCRORCIDObjectResource.java +++ b/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/rest/resources/MCRORCIDObjectResource.java @@ -39,7 +39,7 @@ import org.mycore.orcid2.user.MCRORCIDSessionUtils; import org.mycore.orcid2.user.MCRORCIDUser; import org.mycore.orcid2.user.MCRORCIDUserUtils; -import org.mycore.orcid2.util.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRIdentifier; import org.mycore.orcid2.v3.transformer.MCRORCIDWorkTransformerHelper; import org.mycore.orcid2.v3.work.MCRORCIDWorkService; import org.mycore.orcid2.v3.work.MCRORCIDWorkUtils; diff --git a/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkEventHandlerImpl.java b/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkEventHandlerImpl.java index 3438e90538..ef532ec27a 100644 --- a/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkEventHandlerImpl.java +++ b/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkEventHandlerImpl.java @@ -23,7 +23,7 @@ import org.mycore.common.content.MCRJDOMContent; import org.mycore.orcid2.client.MCRORCIDCredential; import org.mycore.orcid2.metadata.MCRORCIDPutCodeInfo; -import org.mycore.orcid2.util.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRIdentifier; import org.mycore.orcid2.v3.transformer.MCRORCIDWorkTransformerHelper; import org.mycore.orcid2.work.MCRORCIDWorkEventHandler; import org.orcid.jaxb.model.v3.release.record.Work; diff --git a/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkService.java b/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkService.java index 14e1191462..ef2bad670c 100644 --- a/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkService.java +++ b/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkService.java @@ -42,7 +42,7 @@ import org.mycore.orcid2.metadata.MCRORCIDMetadataUtils; import org.mycore.orcid2.metadata.MCRORCIDPutCodeInfo; import org.mycore.orcid2.metadata.MCRORCIDUserInfo; -import org.mycore.orcid2.util.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRIdentifier; import org.mycore.orcid2.v3.client.MCRORCIDClientHelper; import org.mycore.orcid2.v3.client.MCRORCIDSearchImpl; import org.mycore.orcid2.v3.client.MCRORCIDSectionImpl; diff --git a/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkSummaryUtils.java b/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkSummaryUtils.java index 1416cc82d4..d5589e10c9 100644 --- a/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkSummaryUtils.java +++ b/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkSummaryUtils.java @@ -33,7 +33,7 @@ import org.mycore.orcid2.exception.MCRORCIDException; import org.mycore.orcid2.exception.MCRORCIDTransformationException; import org.mycore.orcid2.metadata.MCRORCIDPutCodeInfo; -import org.mycore.orcid2.util.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRIdentifier; import org.mycore.orcid2.v3.transformer.MCRORCIDWorkTransformerHelper; import org.orcid.jaxb.model.v3.release.record.summary.WorkSummary; diff --git a/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkUtils.java b/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkUtils.java index c3c1526a85..cc38fd2aaa 100644 --- a/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkUtils.java +++ b/mycore-orcid2/src/main/java/org/mycore/orcid2/v3/work/MCRORCIDWorkUtils.java @@ -32,7 +32,7 @@ import org.mycore.orcid2.MCRORCIDUtils; import org.mycore.orcid2.exception.MCRORCIDException; import org.mycore.orcid2.exception.MCRORCIDTransformationException; -import org.mycore.orcid2.util.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRIdentifier; import org.mycore.orcid2.v3.transformer.MCRORCIDWorkTransformerHelper; import org.orcid.jaxb.model.common.Relationship; import org.orcid.jaxb.model.v3.release.common.Contributor; diff --git a/mycore-orcid2/src/main/java/org/mycore/orcid2/work/MCRORCIDWorkEventHandler.java b/mycore-orcid2/src/main/java/org/mycore/orcid2/work/MCRORCIDWorkEventHandler.java index 4fa10df154..d80e075aff 100644 --- a/mycore-orcid2/src/main/java/org/mycore/orcid2/work/MCRORCIDWorkEventHandler.java +++ b/mycore-orcid2/src/main/java/org/mycore/orcid2/work/MCRORCIDWorkEventHandler.java @@ -53,7 +53,7 @@ import org.mycore.orcid2.user.MCRORCIDUser; import org.mycore.orcid2.user.MCRORCIDUserProperties; import org.mycore.orcid2.user.MCRORCIDUserUtils; -import org.mycore.orcid2.util.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRIdentifier; import org.mycore.user2.MCRUser; import org.orcid.jaxb.model.message.ScopeConstants; diff --git a/mycore-orcid2/src/main/resources/components/orcid2/config/mycore.properties b/mycore-orcid2/src/main/resources/components/orcid2/config/mycore.properties index b1ecd6893f..780ec89217 100644 --- a/mycore-orcid2/src/main/resources/components/orcid2/config/mycore.properties +++ b/mycore-orcid2/src/main/resources/components/orcid2/config/mycore.properties @@ -105,3 +105,6 @@ MCR.ORCID2.Object.TrustedIdentifierTypes= # XPath for the selection of the publication date MCR.ORCID2.Mods.DateIssued.XPath=(mods:originInfo/mods:dateIssued[@encoding='w3cdtf'][@keyDate='yes'],descendant::mods:relatedItem[@type='host'][not(ancestor::mods:relatedItem[not(@type='host')])]/mods:originInfo/mods:dateIssued[@encoding='w3cdtf'][@keyDate='yes'],mods:originInfo/mods:dateIssued[@encoding='w3cdtf'],descendant::mods:relatedItem[@type='host'][not(ancestor::mods:relatedItem[not(@type='host')])]/mods:originInfo/mods:dateIssued[@encoding='w3cdtf'])[1] + +# Implementation for accessing all ORCIDs of a user +MCR.ORCID2.LegalEntityService.Class=org.mycore.user2.MCRUserIdentifierService diff --git a/mycore-orcid2/src/test/java/org/mycore/orcid2/user/MCRLegalEntityServiceMock.java b/mycore-orcid2/src/test/java/org/mycore/orcid2/user/MCRLegalEntityServiceMock.java new file mode 100644 index 0000000000..12bdb0c299 --- /dev/null +++ b/mycore-orcid2/src/test/java/org/mycore/orcid2/user/MCRLegalEntityServiceMock.java @@ -0,0 +1,46 @@ +package org.mycore.orcid2.user; + +import org.mycore.datamodel.legalentity.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRLegalEntityService; +import org.mycore.user2.MCRUser; +import org.mycore.user2.MCRUserAttribute; + +import java.util.Set; +import java.util.stream.Collectors; + +/** + * For testing by using an internal {@link MCRUser userMock}. + */ +public class MCRLegalEntityServiceMock implements MCRLegalEntityService { + + private MCRUser userMock; + + public MCRUser getUserMock() { + return this.userMock; + } + + public void setUserMock(MCRUser userMock) { + this.userMock = userMock; + } + + @Override + public Set getAllIdentifiers(MCRIdentifier identifier) { + return userMock.getAttributes().stream() + .map(attr -> new MCRIdentifier(attr.getName(), attr.getValue())) + .collect(Collectors.toSet()); + } + + @Override + public Set getTypedIdentifiers(MCRIdentifier primaryIdentifier, String identifierType) { + return userMock.getAttributes().stream() + .filter(attr -> attr.getName().substring("_id".length()).equals(identifierType)) + .map(attr -> new MCRIdentifier(attr.getName(), attr.getValue())) + .collect(Collectors.toSet()); + } + + @Override + public void addIdentifier(MCRIdentifier primaryIdentifier, MCRIdentifier identifierToAdd) { + userMock.getAttributes().add(new MCRUserAttribute( + "id_" + identifierToAdd.getType(), identifierToAdd.getValue())); + } +} diff --git a/mycore-orcid2/src/test/java/org/mycore/orcid2/user/MCRORCIDUserTest.java b/mycore-orcid2/src/test/java/org/mycore/orcid2/user/MCRORCIDUserTest.java index c912b2ba28..d2458c4e85 100644 --- a/mycore-orcid2/src/test/java/org/mycore/orcid2/user/MCRORCIDUserTest.java +++ b/mycore-orcid2/src/test/java/org/mycore/orcid2/user/MCRORCIDUserTest.java @@ -18,53 +18,109 @@ package org.mycore.orcid2.user; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.mycore.datamodel.legalentity.MCRIdentifier; import org.mycore.orcid2.client.MCRORCIDCredential; +import org.mycore.orcid2.exception.MCRORCIDException; import org.mycore.test.MCRJPAExtension; import org.mycore.test.MyCoReTest; import org.mycore.user2.MCRUser; -import org.mycore.user2.MCRUserManager; +import org.mycore.user2.MCRUserAttribute; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertNotNull; @MyCoReTest @ExtendWith(MCRJPAExtension.class) public class MCRORCIDUserTest { private static final String ORCID = "0000-0001-2345-6789"; + private static final String ORCID_2 = "0000-0002-2345-6789"; + private static final String ORCID_3 = "0000-0003-2345-6789"; private static final String ACCESS_TOKEN = "accessToken"; + private static MCRORCIDUser orcidUser; + + private static MCRUser userMock; + + @BeforeEach + public void prepare() throws NoSuchFieldException, IllegalAccessException { + userMock = new MCRUser("junit"); + MCRLegalEntityServiceMock legalEntityServiceMock = new MCRLegalEntityServiceMock(); + legalEntityServiceMock.setUserMock(userMock); + orcidUser = new MCRORCIDUser(userMock, legalEntityServiceMock); + } + @Test public void testStoreGetCredentials() { - MCRUser user = new MCRUser("junit"); - MCRUserManager.createUser(user); - MCRORCIDUser orcidUser = new MCRORCIDUser(user); assertEquals(0, orcidUser.getCredentials().size()); final MCRORCIDCredential credential = new MCRORCIDCredential(ACCESS_TOKEN); orcidUser.addCredential(ORCID, credential); // id_orcid + orcid_credential_orcid - assertEquals(2, user.getAttributes().size()); - assertNotNull(user.getUserAttribute("orcid_credential_" + ORCID)); - assertEquals(ORCID, user.getUserAttribute("id_orcid")); + assertEquals(2, userMock.getAttributes().size()); + assertNotNull(userMock.getUserAttribute("orcid_credential_" + ORCID)); + assertEquals(ORCID, userMock.getUserAttribute("id_orcid")); assertEquals(credential, orcidUser.getCredentialByORCID(ORCID)); } @Test public void testRemoveAllCredentials() { - MCRUser user = new MCRUser("junit"); - MCRUserManager.createUser(user); - MCRORCIDUser orcidUser = new MCRORCIDUser(user); final MCRORCIDCredential credential = new MCRORCIDCredential(ACCESS_TOKEN); orcidUser.addCredential(ORCID, credential); - user.setUserAttribute("test", "test"); + userMock.setUserAttribute("test", "test"); orcidUser.removeAllCredentials(); // id_orcid + test - assertEquals(2, user.getAttributes().size()); - assertEquals(ORCID, user.getUserAttribute("id_orcid")); - assertEquals("test", user.getUserAttribute("test")); + assertEquals(2, userMock.getAttributes().size()); + assertEquals(ORCID, userMock.getUserAttribute("id_orcid")); + assertEquals("test", userMock.getUserAttribute("test")); + } + + @Test + public void testAddInvalidCredentials() { + assertEquals(0, orcidUser.getCredentials().size()); + final MCRORCIDCredential credential = new MCRORCIDCredential(null); + assertThrows(MCRORCIDException.class, () -> orcidUser.addCredential(ORCID, credential)); + assertEquals(0, orcidUser.getCredentials().size()); + } + + @Test + public void testGetORCIDs() { + userMock.setUserAttribute("test", "test"); + userMock.getAttributes().add(new MCRUserAttribute("id_orcid", ORCID)); + userMock.getAttributes().add(new MCRUserAttribute("id_orcid", ORCID_2)); + userMock.getAttributes().add(new MCRUserAttribute("id_orcid", ORCID_3)); + Set orcids = orcidUser.getORCIDs(); + assertEquals(Set.of(ORCID, ORCID_2, ORCID_3), orcids); + } + + @Test + public void testAddORCID() { + assertEquals(0, orcidUser.getORCIDs().size()); + orcidUser.addORCID(ORCID); + assertEquals(1, orcidUser.getORCIDs().size()); + assertEquals(Set.of(ORCID), orcidUser.getORCIDs()); + } + + @Test + public void testAddInvalidORCID() { + assertEquals(0, orcidUser.getORCIDs().size()); + assertThrows(MCRORCIDException.class, () -> orcidUser.addORCID("1234")); + assertEquals(0, orcidUser.getORCIDs().size()); + } + + @Test + public void testGetIdentifiers() { + userMock.setUserAttribute("test", "test"); + userMock.getAttributes().add(new MCRUserAttribute("id_orcid", ORCID)); + Set identifiers = orcidUser.getIdentifiers(); + assertEquals(Set.of(new MCRIdentifier("test", "test"), + new MCRIdentifier("id_orcid", ORCID)), identifiers); } } diff --git a/mycore-user2/src/main/java/org/mycore/user2/MCRUserIdentifierService.java b/mycore-user2/src/main/java/org/mycore/user2/MCRUserIdentifierService.java new file mode 100644 index 0000000000..d28c3e35d1 --- /dev/null +++ b/mycore-user2/src/main/java/org/mycore/user2/MCRUserIdentifierService.java @@ -0,0 +1,103 @@ +/* + * This file is part of *** M y C o R e *** + * See https://www.mycore.de/ for details. + * + * MyCoRe is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MyCoRe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MyCoRe. If not, see . + */ + +package org.mycore.user2; + +import org.mycore.datamodel.legalentity.MCRIdentifier; +import org.mycore.datamodel.legalentity.MCRLegalEntityService; + +import java.util.Collections; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; + +public class MCRUserIdentifierService implements MCRLegalEntityService { + + public static final String ATTR_ID_PREFIX = "id_"; + + /** + * Gets all {@link MCRIdentifier MCRIdentifiers} of a user by its {@link MCRUser#getUserID() user ID}. + * @param userId the user id + * @return all identifiers with the prefix {@link MCRUserIdentifierService#ATTR_ID_PREFIX} + * or an empty set. prefix is stripped + */ + @Override + public Set getAllIdentifiers(MCRIdentifier userId) { + return findUserByUserID(userId) + .map(user -> user.getAttributes().stream() + .filter(a -> a.getName().startsWith(ATTR_ID_PREFIX)) + .map(a -> new MCRIdentifier(stripPrefix(a.getName()), a.getValue())) + .collect(Collectors.toSet())) + .orElse(Collections.emptySet()); + } + + /** + * Gets a user's {@link MCRIdentifier MCRIdentifiers} of a specified type by its + * {@link MCRUser#getUserID() user ID}. + * @param userId the user id + * @param identifierType the type of identifier to filter for, without prefix + * @return all identifiers of the specified type containing the prefix + * {@link MCRUserIdentifierService#ATTR_ID_PREFIX} or an empty set. prefix is stripped + */ + @Override + public Set getTypedIdentifiers(MCRIdentifier userId, String identifierType) { + return findUserByUserID(userId) + .map(user -> user.getAttributes().stream() + .filter(a -> stripPrefix(a.getName()).equals(identifierType)) + .map(a -> new MCRIdentifier(stripPrefix(a.getName()), a.getValue())) + .collect(Collectors.toSet())) + .orElse(Collections.emptySet()); + } + + /** + * Adds an attribute to a user by its {@link MCRUser#getUserID() user ID}. + * @param userId the user id + * @param attributeToAdd the attribute to add in the form of a {@link MCRIdentifier} + */ + @Override + public void addIdentifier(MCRIdentifier userId, MCRIdentifier attributeToAdd) { + findUserByUserID(userId).ifPresent(user -> { + MCRUserAttribute newAttribute = new MCRUserAttribute( + ATTR_ID_PREFIX + attributeToAdd.getType(), attributeToAdd.getValue()); + if (user.getAttributes().add(newAttribute)) { + MCRUserManager.updateUser(user); + } + }); + } + + /** + * Takes a user id and returns an Optional with the corresponding user. + * @param userId the user id + * @return a nullable Optional that might contain a user + */ + private Optional findUserByUserID(MCRIdentifier userId) { + if (userId == null) { + return Optional.empty(); + } + if (!"userid".equals(userId.getType())) { + return Optional.empty(); + } + MCRUser user = MCRUserManager.getUser(userId.getValue()); + return Optional.ofNullable(user); + } + + private String stripPrefix(String name) { + return name.startsWith(ATTR_ID_PREFIX) ? name.substring(ATTR_ID_PREFIX.length()) : name; + } + +} diff --git a/mycore-user2/src/test/java/org/mycore/user2/MCRUserIdentifierServiceTest.java b/mycore-user2/src/test/java/org/mycore/user2/MCRUserIdentifierServiceTest.java new file mode 100644 index 0000000000..7f1603dbb4 --- /dev/null +++ b/mycore-user2/src/test/java/org/mycore/user2/MCRUserIdentifierServiceTest.java @@ -0,0 +1,130 @@ +/* + * This file is part of *** M y C o R e *** + * See https://www.mycore.de/ for details. + * + * MyCoRe is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MyCoRe is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MyCoRe. If not, see . + */ + +package org.mycore.user2; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mycore.datamodel.legalentity.MCRIdentifier; +import org.mycore.test.MCRJPAExtension; +import org.mycore.test.MyCoReTest; + +import java.util.Set; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +@MyCoReTest +@ExtendWith({ MCRJPAExtension.class, MCRUserExtension.class }) +public class MCRUserIdentifierServiceTest { + + private static final String ORCID_1 = "0000-0001-2345-6789"; + + private static final String ORCID_2 = "0000-0002-3456-7895"; + + private static final String ORCID_3 = "0000-0003-4567-8985"; + + private static final String SCOPUS = "87654321"; + + MCRUserIdentifierService service; + + MCRUser user; + + @BeforeEach + public void setUp() throws Exception { + user = new MCRUser("john"); + user.setRealName("John Doe"); + user.getAttributes().add(new MCRUserAttribute("id_orcid", ORCID_1)); + user.getAttributes().add(new MCRUserAttribute("id_orcid", ORCID_2)); + user.getAttributes().add(new MCRUserAttribute("id_orcid", ORCID_3)); + user.setUserAttribute("id_scopus", SCOPUS); + user.setUserAttribute("other", "abc"); + MCRUserManager.createUser(user); + service = new MCRUserIdentifierService(); + } + + @Test + public final void testGetAllIdentifiers() { + Set allIdentifiers = service.getAllIdentifiers( + new MCRIdentifier("userid", user.getUserID())); + Set expected = Set.of(new MCRIdentifier("orcid", ORCID_1), + new MCRIdentifier("orcid", ORCID_2), + new MCRIdentifier("orcid", ORCID_3), + new MCRIdentifier("scopus", SCOPUS)); + assertEquals(expected, allIdentifiers); + } + + @Test + public final void testGetTypedIdentifiers() { + final MCRIdentifier userid = new MCRIdentifier("userid", user.getUserID()); + Set typedIdentifiers = service.getTypedIdentifiers(userid, "orcid"); + Set expected = Set.of(new MCRIdentifier("orcid", ORCID_1), + new MCRIdentifier("orcid", ORCID_2), + new MCRIdentifier("orcid", ORCID_3)); + assertEquals(expected, typedIdentifiers); + + typedIdentifiers = service.getTypedIdentifiers(userid, "id_orcid"); + assertEquals(0, typedIdentifiers.size()); + + typedIdentifiers = service.getTypedIdentifiers(userid, "scopus"); + assertEquals(Set.of(new MCRIdentifier("scopus", SCOPUS)), typedIdentifiers); + + typedIdentifiers = service.getTypedIdentifiers(userid, "other"); + assertEquals(Set.of(new MCRIdentifier("other", "abc")), typedIdentifiers); + } + + @Test + public final void testAddIdentifier() { + MCRUser user1 = new MCRUser("jane"); + user1.setRealName("Jane Doe"); + user1.getAttributes().add(new MCRUserAttribute("id_orcid", ORCID_1)); + user1.getAttributes().add(new MCRUserAttribute("id_orcid", ORCID_2)); + MCRUserManager.createUser(user1); + + final MCRIdentifier userid = new MCRIdentifier("userid", user1.getUserID()); + + Set allIdentifiers = service.getAllIdentifiers(userid); + assertEquals(2, allIdentifiers.size()); + + service.addIdentifier(userid, new MCRIdentifier("orcid", ORCID_1)); // don't add id twice + allIdentifiers = service.getAllIdentifiers(userid); + assertEquals(2, allIdentifiers.size()); + + service.addIdentifier(userid, new MCRIdentifier("orcid", ORCID_3)); + allIdentifiers = service.getAllIdentifiers(userid); + assertEquals(3, allIdentifiers.size()); + Set expected = Set.of(new MCRIdentifier("orcid", ORCID_1), + new MCRIdentifier("orcid", ORCID_2), + new MCRIdentifier("orcid", ORCID_3)); + assertEquals(expected, allIdentifiers); + } + + @Test + public final void testNoUser() { + MCRIdentifier nonameUserid = new MCRIdentifier("userid", "noname"); + Set allIdentifiers = service.getAllIdentifiers(nonameUserid); + assertEquals(0, allIdentifiers.size()); + + Set typedIdentifiers = service.getTypedIdentifiers(nonameUserid, "orcid"); + assertEquals(0, typedIdentifiers.size()); + + service.addIdentifier(nonameUserid, new MCRIdentifier("orcid", ORCID_1)); + allIdentifiers = service.getAllIdentifiers(nonameUserid); + assertEquals(0, allIdentifiers.size()); + } +}