diff --git a/src/main/java/org/gbif/collections/sync/SyncResult.java b/src/main/java/org/gbif/collections/sync/SyncResult.java index c08b44f..df1a8a3 100644 --- a/src/main/java/org/gbif/collections/sync/SyncResult.java +++ b/src/main/java/org/gbif/collections/sync/SyncResult.java @@ -1,6 +1,7 @@ package org.gbif.collections.sync; import org.gbif.api.model.collections.Collection; +import org.gbif.api.model.collections.CollectionEntity; import org.gbif.api.model.collections.Contact; import org.gbif.api.model.collections.Institution; @@ -10,6 +11,7 @@ import lombok.Builder; import lombok.Data; import lombok.Singular; +import org.gbif.api.model.collections.suggestions.ChangeSuggestion; /** * Holds the result of a sync. @@ -72,6 +74,7 @@ public static class NoEntityMatch { private Institution newInstitution; private Collection newCollection; private ContactMatch contactMatch; + private int newChangeSuggestion; } @Data diff --git a/src/main/java/org/gbif/collections/sync/clients/http/GrSciCollHttpClient.java b/src/main/java/org/gbif/collections/sync/clients/http/GrSciCollHttpClient.java index ae9e2ad..dbb4c3d 100644 --- a/src/main/java/org/gbif/collections/sync/clients/http/GrSciCollHttpClient.java +++ b/src/main/java/org/gbif/collections/sync/clients/http/GrSciCollHttpClient.java @@ -4,6 +4,7 @@ import org.gbif.api.model.collections.Contact; import org.gbif.api.model.collections.Institution; import org.gbif.api.model.collections.MasterSourceMetadata; +import org.gbif.api.model.collections.suggestions.ChangeSuggestion; import org.gbif.api.model.common.paging.PagingResponse; import org.gbif.api.model.registry.Identifier; import org.gbif.api.model.registry.MachineTag; @@ -121,6 +122,26 @@ public List getIhInstitutions() { return result; } + public List getInstitutionsByName(String name) { + List result = new ArrayList<>(); + + boolean endRecords = false; + int offset = 0; + while (!endRecords) { + PagingResponse response = + syncCall(api.listInstitutionsByName(name, 1000, offset)); + endRecords = response.isEndOfRecords(); + offset += response.getLimit(); + result.addAll(response.getResults()); + } + + return result; + } + + public int createChangeSuggestion(ChangeSuggestion changeSuggestion) { + return syncCall(api.createChangeSuggestion(changeSuggestion)); + } + public Institution getInstitution(UUID key) { return syncCall(api.getInstitution(key)); } @@ -259,6 +280,12 @@ Call> listInstitutions( @Query("limit") int limit, @Query("offset") int offset); + @GET("institution") + Call> listInstitutionsByName( + @Query("name") String name, + @Query("limit") int limit, + @Query("offset") int offset); + @GET("institution/{key}") Call getInstitution(@Path("key") UUID key); @@ -357,6 +384,9 @@ Call addMasterSourceMetadataToInstitution( @POST("collection/{collectionKey}/masterSourceMetadata") Call addMasterSourceMetadataToCollection( @Path("collectionKey") UUID collectionKey, @Body MasterSourceMetadata masterSourceMetadata); + + @POST("changeSuggestion") + Call createChangeSuggestion(@Body ChangeSuggestion createSuggestion); } /** Adapter necessary for retrofit due to versioning. */ diff --git a/src/main/java/org/gbif/collections/sync/clients/proxy/BaseProxyClient.java b/src/main/java/org/gbif/collections/sync/clients/proxy/BaseProxyClient.java index a6167b2..f8276a8 100644 --- a/src/main/java/org/gbif/collections/sync/clients/proxy/BaseProxyClient.java +++ b/src/main/java/org/gbif/collections/sync/clients/proxy/BaseProxyClient.java @@ -1,8 +1,10 @@ package org.gbif.collections.sync.clients.proxy; +import java.util.List; import org.gbif.api.model.collections.Collection; import org.gbif.api.model.collections.Contact; import org.gbif.api.model.collections.Institution; +import org.gbif.api.model.collections.suggestions.ChangeSuggestion; import org.gbif.collections.sync.clients.http.GrSciCollHttpClient; import org.gbif.collections.sync.common.handler.CollectionHandler; import org.gbif.collections.sync.common.handler.InstitutionHandler; @@ -57,6 +59,16 @@ public void removeContactFromInstitution(UUID entityKey, int contactKey) { institutionHandler.removeContactFromEntityCall(entityKey, contactKey); } + @Override + public List findInstitutionByName(String institutionName) { + return institutionHandler.listInstitutionsByName(institutionName); + } + + @Override + public int createChangeSuggestion(ChangeSuggestion createSuggestion) { + return institutionHandler.createChangeSuggestion(createSuggestion); + } + public Integer addContactToCollection(UUID entityKey, Contact contact) { return collectionHandler.addContactToEntityCall(entityKey, contact); } diff --git a/src/main/java/org/gbif/collections/sync/clients/proxy/GrSciCollProxyClient.java b/src/main/java/org/gbif/collections/sync/clients/proxy/GrSciCollProxyClient.java index 0e1bd79..73c8936 100644 --- a/src/main/java/org/gbif/collections/sync/clients/proxy/GrSciCollProxyClient.java +++ b/src/main/java/org/gbif/collections/sync/clients/proxy/GrSciCollProxyClient.java @@ -1,7 +1,9 @@ package org.gbif.collections.sync.clients.proxy; +import java.util.List; import org.gbif.api.model.collections.Collection; import org.gbif.api.model.collections.Institution; +import org.gbif.api.model.collections.suggestions.ChangeSuggestion; public interface GrSciCollProxyClient { @@ -12,4 +14,8 @@ public interface GrSciCollProxyClient { Collection createCollection(Collection newCollection); boolean updateCollection(Collection oldCollection, Collection newCollection); + + List findInstitutionByName(String institutionName); + + int createChangeSuggestion(ChangeSuggestion createSuggestion); } diff --git a/src/main/java/org/gbif/collections/sync/common/BaseSynchronizer.java b/src/main/java/org/gbif/collections/sync/common/BaseSynchronizer.java index 4cf4639..ef21493 100644 --- a/src/main/java/org/gbif/collections/sync/common/BaseSynchronizer.java +++ b/src/main/java/org/gbif/collections/sync/common/BaseSynchronizer.java @@ -3,6 +3,7 @@ import org.gbif.api.model.collections.Collection; import org.gbif.api.model.collections.Contact; import org.gbif.api.model.collections.Institution; +import org.gbif.api.model.collections.suggestions.InstitutionChangeSuggestion; import org.gbif.collections.sync.SyncResult.*; import org.gbif.collections.sync.clients.proxy.GrSciCollProxyClient; import org.gbif.collections.sync.common.converter.EntityConverter; @@ -128,23 +129,32 @@ public InstitutionAndCollectionMatch handleInstAndCollMatch(MatchResult ma public NoEntityMatch handleNoMatch(MatchResult matchResult) { // create institution Institution newInstitution = entityConverter.convertToInstitution(matchResult.getSource()); - - Institution createdInstitution = proxyClient.createInstitution(newInstitution); - - // create collection - Collection createdCollection = createCollection(matchResult.getSource(), createdInstitution); - - // same staff for both entities - ContactMatch contactMatchInstitution = - staffResultHandler.handleStaff(matchResult, createdInstitution); - ContactMatch contactMatchCollection = - staffResultHandler.handleStaff(matchResult, createdCollection); - - return NoEntityMatch.builder() - .newCollection(createdCollection) - .newInstitution(createdInstitution) - .contactMatch(mergeContactMatches(contactMatchInstitution, contactMatchCollection)) - .build(); + if (proxyClient.findInstitutionByName(newInstitution.getName()).isEmpty()) { + Institution createdInstitution = proxyClient.createInstitution(newInstitution); + // create collection + Collection createdCollection = createCollection(matchResult.getSource(), createdInstitution); + + // same staff for both entities + ContactMatch contactMatchInstitution = + staffResultHandler.handleStaff(matchResult, createdInstitution); + ContactMatch contactMatchCollection = + staffResultHandler.handleStaff(matchResult, createdCollection); + + return NoEntityMatch.builder() + .newCollection(createdCollection) + .newInstitution(createdInstitution) + .contactMatch(mergeContactMatches(contactMatchInstitution, contactMatchCollection)) + .build(); + } + else { + // create change suggestion + InstitutionChangeSuggestion institutionChangeSuggestion = new InstitutionChangeSuggestion(); + institutionChangeSuggestion.setSuggestedEntity(newInstitution); + int suggestionCreated = proxyClient.createChangeSuggestion(institutionChangeSuggestion); + return NoEntityMatch.builder() + .newChangeSuggestion(suggestionCreated) + .build(); + } } @VisibleForTesting diff --git a/src/main/java/org/gbif/collections/sync/common/handler/InstitutionHandler.java b/src/main/java/org/gbif/collections/sync/common/handler/InstitutionHandler.java index 4673c6b..a75b45a 100644 --- a/src/main/java/org/gbif/collections/sync/common/handler/InstitutionHandler.java +++ b/src/main/java/org/gbif/collections/sync/common/handler/InstitutionHandler.java @@ -1,8 +1,10 @@ package org.gbif.collections.sync.common.handler; +import java.util.List; import org.gbif.api.model.collections.Contact; import org.gbif.api.model.collections.Institution; import org.gbif.api.model.collections.MasterSourceMetadata; +import org.gbif.api.model.collections.suggestions.ChangeSuggestion; import org.gbif.api.model.registry.Identifier; import org.gbif.api.model.registry.MachineTag; import org.gbif.collections.sync.clients.http.GrSciCollHttpClient; @@ -75,4 +77,12 @@ public void removeContactFromEntityCall(UUID entityKey, int contactKey) { () -> grSciCollHttpClient.removeContactFromInstitution(entityKey, contactKey), exceptionHandler(contactKey, "Failed to remove contact from institution " + entityKey)); } + + public List listInstitutionsByName(String name) { + return grSciCollHttpClient.getInstitutionsByName(name); + } + + public int createChangeSuggestion(ChangeSuggestion changeSuggestion) { + return grSciCollHttpClient.createChangeSuggestion(changeSuggestion); + } } diff --git a/src/main/java/org/gbif/collections/sync/ih/IHSynchronizer.java b/src/main/java/org/gbif/collections/sync/ih/IHSynchronizer.java index 7fc921d..0084a7d 100644 --- a/src/main/java/org/gbif/collections/sync/ih/IHSynchronizer.java +++ b/src/main/java/org/gbif/collections/sync/ih/IHSynchronizer.java @@ -79,8 +79,7 @@ public SyncResult sync() { return; } - IHMatchResult match = matcher.match(ihInstitution); - handleResult(match, resultBuilder); + IHMatchResult match = matcher.match(ihInstitution);handleResult(match, resultBuilder); }); SyncResult result = resultBuilder.build(); diff --git a/src/test/java/org/gbif/collections/sync/ih/BaseIHTest.java b/src/test/java/org/gbif/collections/sync/ih/BaseIHTest.java index 12bd74d..0d43a57 100644 --- a/src/test/java/org/gbif/collections/sync/ih/BaseIHTest.java +++ b/src/test/java/org/gbif/collections/sync/ih/BaseIHTest.java @@ -12,7 +12,6 @@ import org.gbif.api.vocabulary.Country; import org.gbif.api.vocabulary.IdentifierType; import org.gbif.api.vocabulary.collections.IdType; -import org.gbif.api.vocabulary.collections.InstitutionType; import org.gbif.api.vocabulary.collections.MasterSourceType; import org.gbif.api.vocabulary.collections.Source; import org.gbif.collections.sync.SyncResult; @@ -382,6 +381,25 @@ protected Map convertCollectionSummary(IHInstitution.Collection return map; } + protected TestEntity createExistingInstitutionWithSameName() { + Institution i = new Institution(); + i.setKey(UUID.randomUUID()); + i.setCode("bar"); + i.setName("bar"); + i.setNumberSpecimens(1000); + i.setMasterSource(MasterSourceType.IH); + i.setMasterSourceMetadata(new MasterSourceMetadata(Source.IH_IRN, IRN_TEST)); + i.getIdentifiers().add(new Identifier(IdentifierType.IH_IRN, IRN_TEST)); + i.getIdentifiers().add(new Identifier(IdentifierType.CITES, CITES_TEST)); + + IHInstitution ih = new IHInstitution(); + ih.setCode("bar"); + ih.setOrganization("bar"); + ih.setSpecimenTotal(1000); + + return TestEntity.builder().entity(i).ih(ih).build(); + } + private static IHConfig createConfig() { IHConfig ihConfig = new IHConfig(); ihConfig.setSyncConfig(createTestSyncConfig()); diff --git a/src/test/java/org/gbif/collections/sync/ih/IHSynchronizerHandlersTest.java b/src/test/java/org/gbif/collections/sync/ih/IHSynchronizerHandlersTest.java index 490fa42..8fcd197 100644 --- a/src/test/java/org/gbif/collections/sync/ih/IHSynchronizerHandlersTest.java +++ b/src/test/java/org/gbif/collections/sync/ih/IHSynchronizerHandlersTest.java @@ -119,6 +119,10 @@ public void noMatchTest() { assertEmptyContactMatch(noEntityMatch.getContactMatch()); } + @Test + public void noMatchButNameExistsTest() { + + } @Test public void institutionAndCollectionMatchTest() { TestEntity collectionToUpdate = createCollectionToUpdate();