Skip to content

Commit

Permalink
Merge branch 'dev' into #343_suggest_change_and_log
Browse files Browse the repository at this point in the history
  • Loading branch information
marcos-lg committed May 6, 2021
2 parents f609ad2 + 59fb185 commit 33c27f1
Show file tree
Hide file tree
Showing 9 changed files with 191 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ public class Datasets extends JsonBackedData<Dataset> {
public static final String DATASET_RIGHTS = "The rights";
public static final License DATASET_LICENSE = License.CC_BY_NC_4_0;
public static final DOI DATASET_DOI = new DOI(DOI.TEST_PREFIX, "gbif.2014.XSD123");
public static final Citation DATASET_CITATION = new Citation("This is a citation text", "ABC");
public static final Citation DATASET_CITATION = new Citation("This is a citation text", "ABC", true);

@Autowired
public Datasets(
Expand Down Expand Up @@ -101,7 +101,7 @@ public Dataset newPersistedInstance(UUID organizationKey, UUID installationKey)
return datasetService.get(key);
}

public static String buildExpectedCitation(Dataset dataset, String organizationTitle) {
public static CitationGenerator.CitationData buildExpectedCitation(Dataset dataset, String organizationTitle) {
return CitationGenerator.generateCitation(dataset, organizationTitle);
}

Expand All @@ -112,9 +112,9 @@ public static String buildExpectedCitation(Dataset dataset, String organizationT
* @return a mutable mpa in case more properties shall be added.
*/
public static Map<String, Object> buildExpectedProcessedProperties(Dataset dataset) {
String expectedCitation = buildExpectedCitation(dataset, Organizations.ORGANIZATION_TITLE);
CitationGenerator.CitationData expectedCitation = buildExpectedCitation(dataset, Organizations.ORGANIZATION_TITLE);
Map<String, Object> processedProperties = new HashMap<>();
processedProperties.put("citation.text", expectedCitation);
processedProperties.put("citation.text", expectedCitation.getCitation().getText());
return processedProperties;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -798,7 +798,7 @@ private void validateExistingIptDataset(
// per https://github.com/gbif/registry/issues/4, Citation is now generated
assertNotNull(dataset.getCitation());
assertEquals(
Datasets.buildExpectedCitation(dataset, Organizations.ORGANIZATION_TITLE),
Datasets.buildExpectedCitation(dataset, Organizations.ORGANIZATION_TITLE).getCitation().getText(),
dataset.getCitation().getText());
assertEquals(Datasets.DATASET_ABBREVIATION, dataset.getAbbreviation());
assertEquals(Datasets.DATASET_ALIAS, dataset.getAlias());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ private void validateExistingDataset(
// per https://github.com/gbif/registry/issues/4, Citation is now generated
assertNotNull(dataset.getCitation());
assertEquals(
Datasets.buildExpectedCitation(dataset, Organizations.ORGANIZATION_TITLE),
Datasets.buildExpectedCitation(dataset, Organizations.ORGANIZATION_TITLE).getCitation().getText(),
dataset.getCitation().getText());
assertEquals(Datasets.DATASET_ABBREVIATION, dataset.getAbbreviation());
assertEquals(Datasets.DATASET_ALIAS, dataset.getAlias());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"language":"DA",
"citation": {
"text":"This is a citation text",
"identifier":"ABC"
"identifier":"ABC",
"contacts": []
},
"rights":"The rights",
"logoUrl":"http://www.example.org",
Expand Down
4 changes: 4 additions & 0 deletions registry-metadata/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
</dependency>

<!-- Third party dependencies -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-digester3</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package org.gbif.registry.metadata;

import org.gbif.api.model.registry.Citation;
import org.gbif.api.model.registry.CitationContact;
import org.gbif.api.model.registry.Contact;
import org.gbif.api.model.registry.Dataset;
import org.gbif.api.model.registry.Organization;
Expand All @@ -29,13 +31,16 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.StringJoiner;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import lombok.Builder;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

/**
Expand All @@ -44,19 +49,30 @@
*/
public class CitationGenerator {

@Data
@Builder
public static class CitationData {

private final Citation citation;
private final List<CitationContact> contacts;

}

private static final ZoneId UTC = ZoneId.of("UTC");
private static final ContactType MANDATORY_CONTACT_TYPE = ContactType.ORIGINATOR;
private static final EnumSet<ContactType> AUTHOR_CONTACT_TYPE =
EnumSet.of(ContactType.ORIGINATOR, ContactType.METADATA_AUTHOR);
private static final Predicate<Contact> IS_NAME_PROVIDED_FCT =
ctc -> StringUtils.isNotBlank(ctc.getLastName());
private static final Predicate<CitationContact> IS_CONTACT_NAME_PROVIDED =
ctc -> StringUtils.isNotBlank(ctc.getLastName());
private static final Predicate<Contact> IS_ELIGIBLE_CONTACT_TYPE =
ctc -> ctc.getType() != null && AUTHOR_CONTACT_TYPE.contains(ctc.getType());
ctc -> AUTHOR_CONTACT_TYPE.contains(ctc.getType());

/** Utility class */
private CitationGenerator() {}

public static String generateCitation(Dataset dataset, Organization org) {
public static CitationData generateCitation(Dataset dataset, Organization org) {
Objects.requireNonNull(org, "Organization shall be provided");
return generateCitation(dataset, org.getTitle());
}
Expand Down Expand Up @@ -94,19 +110,20 @@ public static String generatePublisherProvidedCitation(Dataset dataset) {
/**
* Generate a citation for a {@link Dataset} and its {@link Organization}. TODO add support for
* i18n
*
* @param dataset
* @param organizationTitle
* @return generated citation as {@link String}
*/
public static String generateCitation(Dataset dataset, String organizationTitle) {
public static CitationData generateCitation(Dataset dataset, String organizationTitle) {

Objects.requireNonNull(dataset, "Dataset shall be provided");
Objects.requireNonNull(organizationTitle, "Organization title shall be provided");

Citation citation = new Citation();

List<CitationContact> contacts = getAuthors(dataset.getContacts());

StringJoiner joiner = new StringJoiner(" ");
List<String> authorsName = generateAuthorsName(getAuthors(dataset.getContacts()));
String authors = authorsName.stream().collect(Collectors.joining(", "));
List<String> authorsName = generateAuthorsName(contacts);
String authors = String.join(", ", authorsName);

boolean authorsNameAvailable = StringUtils.isNotBlank(authors);
authors = authorsNameAvailable ? authors : organizationTitle;
Expand Down Expand Up @@ -149,7 +166,10 @@ public static String generateCitation(Dataset dataset, String organizationTitle)

joiner.add("accessed via GBIF.org on " + LocalDate.now(UTC) + ".");

return joiner.toString();
citation.setText(joiner.toString());
citation.setCitationProvidedBySource(false);

return CitationData.builder().citation(citation).contacts(contacts).build();
}

/**
Expand All @@ -160,18 +180,18 @@ public static String generateCitation(Dataset dataset, String organizationTitle)
* @param contacts list of contacts available
* @return ordered list of authors or empty list, never null
*/
public static List<Contact> getAuthors(List<Contact> contacts) {
public static List<CitationContact> getAuthors(List<Contact> contacts) {
if (contacts == null || contacts.isEmpty()) {
return Collections.emptyList();
}

List<Contact> uniqueContacts =
List<CitationContact> uniqueContacts =
getUniqueAuthors(
contacts, ctc -> IS_NAME_PROVIDED_FCT.and(IS_ELIGIBLE_CONTACT_TYPE).test(ctc));

// make sure we have at least one instance of {@link #MANDATORY_CONTACT_TYPE}
Optional<Contact> firstOriginator =
uniqueContacts.stream().filter(ctc -> MANDATORY_CONTACT_TYPE == ctc.getType()).findFirst();
Optional<CitationContact> firstOriginator =
uniqueContacts.stream().filter(ctc -> ctc.getRoles().contains(MANDATORY_CONTACT_TYPE)).findFirst();

if (firstOriginator.isPresent()) {
return uniqueContacts;
Expand All @@ -186,14 +206,14 @@ public static List<Contact> getAuthors(List<Contact> contacts) {
* @param authors ordered list of authors
* @return list of author names (if it can be generated) or empty list, never null
*/
public static List<String> generateAuthorsName(List<Contact> authors) {
public static List<String> generateAuthorsName(List<CitationContact> authors) {
if (authors == null || authors.isEmpty()) {
return Collections.emptyList();
}

return authors.stream()
.filter(IS_NAME_PROVIDED_FCT)
.map(CitationGenerator::getAuthorName)
.filter(IS_CONTACT_NAME_PROVIDED)
.map(CitationContact::getAbbreviatedName)
.collect(Collectors.toList());
}

Expand All @@ -207,13 +227,32 @@ public static List<String> generateAuthorsName(List<Contact> authors) {
* @param filter {@link Predicate} used to pre-filter contacts
* @return
*/
private static List<Contact> getUniqueAuthors(List<Contact> authors, Predicate<Contact> filter) {
List<Contact> uniqueContact = new ArrayList<>();
private static List<CitationContact> getUniqueAuthors(List<Contact> authors, Predicate<Contact> filter) {
List<CitationContact> uniqueContact = new ArrayList<>();
if (authors != null) {
authors.forEach(
ctc -> {
if (filter.test(ctc) && isNotAlreadyInList(ctc, uniqueContact)) {
uniqueContact.add(ctc);
if (filter.test(ctc)) {
Optional<CitationContact> author = findInAuthorList(ctc, uniqueContact);
if (!author.isPresent()) {
HashSet<ContactType> contactTypes = new HashSet<>();
if(ctc.getType() != null) {
contactTypes.add(ctc.getType());
}
HashSet<String> userIds = new HashSet<>();
if(ctc.getUserId() != null && !ctc.getUserId().isEmpty()) {
userIds.addAll(ctc.getUserId());
}
uniqueContact.add(new CitationContact(ctc.getKey(), getAuthorName(ctc), ctc.getFirstName(), ctc.getLastName(),
contactTypes, userIds));
} else {
author.ifPresent(a -> {
a.getRoles().add(ctc.getType());
if(ctc.getUserId() != null) {
a.getUserId().addAll(ctc.getUserId());
}
});
}
}
});
}
Expand All @@ -228,12 +267,11 @@ private static List<Contact> getUniqueAuthors(List<Contact> authors, Predicate<C
* @param uniqueContact
* @return
*/
private static boolean isNotAlreadyInList(final Contact ctc, List<Contact> uniqueContact) {
return uniqueContact.stream()
.noneMatch(
contact ->
StringUtils.equalsIgnoreCase(ctc.getLastName(), contact.getLastName())
&& StringUtils.equalsIgnoreCase(ctc.getFirstName(), contact.getFirstName()));
private static Optional<CitationContact> findInAuthorList(Contact ctc, List<CitationContact> uniqueContacts) {
return uniqueContacts.stream()
.filter(author -> StringUtils.equalsIgnoreCase(ctc.getLastName(), author.getLastName())
&& StringUtils.equalsIgnoreCase(ctc.getFirstName(), author.getFirstName()))
.findFirst();
}

/**
Expand Down
Loading

0 comments on commit 33c27f1

Please sign in to comment.