Skip to content

Commit

Permalink
Merged in DSC-1631 (pull request DSpace#2014)
Browse files Browse the repository at this point in the history
DSC-1631 Alternative names in submission & multiple affiliation handling
  • Loading branch information
steph-ieffam committed Apr 24, 2024
2 parents 2fc5733 + 6fe3996 commit a33a12b
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 46 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -161,21 +161,33 @@ private Choices getMatches(String text, int start, int limit, String locale, boo
private List<Choice> getChoiceListFromQueryResults(SolrDocumentList results, String searchTitle,
boolean onlyExactMatches) {
return results
.stream()
.map(doc -> {
String title;
if (onlyExactMatches && isForceInternalTitle() || !onlyExactMatches) {
Object fieldValue = doc.getFieldValue("dc.title");
title = fieldValue instanceof String ? (String) fieldValue
: ((ArrayList<String>) fieldValue).get(0);
} else {
title = searchTitle;
}
Map<String, String> extras = ItemAuthorityUtils.buildExtra(getPluginInstanceName(), doc);
return new Choice((String) doc.getFieldValue("search.resourceid"),
title,
title, extras);
}).collect(Collectors.toList());
.stream()
.map(doc -> {
String title = searchTitle;
List<String> objectNames = List.of();
if (onlyExactMatches && isForceInternalTitle() || !onlyExactMatches) {
Object fieldValue = doc.getFieldValue("objectname");
if (fieldValue != null) {
if (fieldValue instanceof String) {
title = (String) fieldValue;
} else {
objectNames = (ArrayList<String>) fieldValue;
title = objectNames.get(0);
}
} else {
title = ((ArrayList<String>) doc.getFieldValue("dc.title"))
.stream()
.findFirst()
.orElse(searchTitle);
}
}
String uuid = (String) doc.getFieldValue("search.resourceid");
Map<String, String> extras = ItemAuthorityUtils.buildExtra(getPluginInstanceName(),
doc, objectNames, uuid);
return new Choice(uuid,
title,
title, extras);
}).collect(Collectors.toList());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -99,7 +100,6 @@ public List<Choice> buildAggregate(String checkAuthorityName, SolrDocument docum
}
} else {
Map<String, String> extras = new HashMap<String, String>();
putValueInExtras(extras, "");
choiceList.add(new Choice((String) document.getFieldValue("search.resourceid"),
title, title, extras));
}
Expand All @@ -110,31 +110,67 @@ public List<Choice> buildAggregate(String checkAuthorityName, SolrDocument docum

protected void buildSingleExtraByMetadata(MetadataValueDTO metadataValue, Map<String, String> extras) {
if (metadataValue == null) {
putValueInExtras(extras, "");
return;
}
if (isDuplicatedValue(metadataValue, extras)) {
return;
}
if (StringUtils.isNotBlank(metadataValue.getAuthority())) {
putValueInExtras(extras, metadataValue.getValue() + "::" + metadataValue.getAuthority());
} else {
if (StringUtils.isNotBlank(metadataValue.getAuthority())) {
putValueInExtras(extras, metadataValue.getValue() + "::" + metadataValue.getAuthority());
} else {
putValueInExtras(extras, metadataValue.getValue());
}
putValueInExtras(extras, metadataValue.getValue());
}
}

private boolean isDuplicatedValue(MetadataValueDTO metadataValue, Map<String, String> extras) {
String key = keyId;
if (useAsData) {
key = "data-" + keyId;
}
String values = extras.get(key);
if (values == null) {
return false;
}

String valueToFind = StringUtils.isNotBlank(metadataValue.getAuthority())
? metadataValue.getValue() + "::" + metadataValue.getAuthority()
: metadataValue.getValue();

if (values.contains("|||")) {
// so it's multivalues
String splittedVals[] = values.split(Pattern.quote("|||"));
return ArrayUtils.contains(splittedVals, valueToFind);
}
return values.equals(valueToFind);

}

protected void buildSingleExtraByRP(SolrDocument solrDocument, Map<String, String> extras) {
List<MetadataValueDTO> metadataValues = getMetadataValueDTOsFromSolr(schema, element, qualifier, solrDocument);
if (metadataValues.isEmpty()) {
buildSingleExtraByMetadata(null, extras);
} else {
buildSingleExtraByMetadata(metadataValues.get(0), extras);
metadataValues.forEach(metadataValue -> {
buildSingleExtraByMetadata(metadataValue, extras);
});
}
}

private void putValueInExtras(Map<String, String> extras, String value) {
if (useAsData) {
extras.put("data-" + keyId, value);
String key = "data-" + keyId;
if (extras.containsKey(key)) {
extras.put(key, extras.get(key) + "|||" + value);
} else {
extras.put(key, value);
}
}
if (useForDisplay) {
extras.put(keyId, value);
if (extras.containsKey(keyId)) {
extras.put(keyId, extras.get(keyId) + "|||" + value);
} else {
extras.put(keyId, value);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/**
* The contents of this file are subject to the license and copyright
* detailed in the LICENSE and NOTICE files at the root of the source
* tree and available online at
*
* http://www.dspace.org/license/
*/
package org.dspace.discovery;

import java.util.List;
import java.util.stream.Collectors;

import org.apache.solr.common.SolrInputDocument;
import org.dspace.content.Item;
import org.dspace.content.MetadataValue;
import org.dspace.content.service.ItemService;
import org.dspace.core.Context;
import org.springframework.beans.factory.annotation.Autowired;

/**
* Implementation of {@link ObjectNameIndexPlugin} which indexes the objectname
* to retrieve alternatives
*
* @author Stefano Maffei at 4science.com
*
*/
public class ObjectNameIndexPlugin implements SolrServiceIndexPlugin {

@Autowired
private ItemService itemService;

public static String OBJECT_NAME_INDEX = "objectname";

public static List<String> fields;

@SuppressWarnings("rawtypes")
@Override
public void additionalIndex(Context context, IndexableObject dso, SolrInputDocument document) {
if (!(dso.getIndexedObject() instanceof Item)) {
return;
}

Item item = (Item) dso.getIndexedObject();
List<String> metadataValues = getMetadataValues(item, fields);

metadataValues.forEach(textValue -> document.addField(OBJECT_NAME_INDEX, textValue));
}

private List<String> getMetadataValues(Item item, List<String> metadataFields) {
return metadataFields.stream()
.flatMap(metadataField -> getMetadataValues(item, metadataField).stream())
.collect(Collectors.toList());
}

private List<String> getMetadataValues(Item item, String metadataField) {
return itemService.getMetadataByMetadataString(item, metadataField).stream()
.map(MetadataValue::getValue)
.collect(Collectors.toList());
}

public static List<String> getFields() {
return fields;
}

public static void setFields(List<String> fields) {
ObjectNameIndexPlugin.fields = fields;
}

}
16 changes: 15 additions & 1 deletion dspace-api/src/main/java/org/dspace/util/ItemAuthorityUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.solr.common.SolrDocument;
import org.dspace.content.authority.Choice;
Expand All @@ -25,7 +26,8 @@ public class ItemAuthorityUtils {
private static DSpace dspace = new DSpace();
private ItemAuthorityUtils() {}

public static Map<String, String> buildExtra(String authorityName, SolrDocument item) {
public static Map<String, String> buildExtra(String authorityName, SolrDocument item,
List<String> objectNames, String uuid) {
Map<String, String> extras = new HashMap<String, String>();
List<ItemAuthorityExtraMetadataGenerator> generators = dspace.getServiceManager()
.getServicesByType(ItemAuthorityExtraMetadataGenerator.class);
Expand All @@ -35,6 +37,18 @@ public static Map<String, String> buildExtra(String authorityName, SolrDocument
extras.putAll(extrasTmp);
}
}
Set<String> alternativeNames = Set.copyOf(objectNames);
if (alternativeNames.size() > 1) {
String alternativeNameKey = "alternative-names";
alternativeNames.forEach(alternativeName -> {
String alternative = alternativeName + "::" + uuid;
if (extras.containsKey(alternativeNameKey)) {
extras.put(alternativeNameKey, extras.get(alternativeNameKey) + "|||" + alternative);
} else {
extras.put(alternativeNameKey, alternative);
}
});
}
return extras;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -127,25 +127,82 @@ public void singleItemAuthorityTest() throws Exception {
Map.of("data-oairecerif_author_affiliation", "OrgUnit_1::"
+ orgUnit_1.getID(),
"oairecerif_author_affiliation", "OrgUnit_1::"
+ orgUnit_1.getID(),
"data-person_identifier_orcid", "",
"person_identifier_orcid", "")),
+ orgUnit_1.getID())),
ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_2.getID().toString(),
"Author 2", "Author 2", "vocabularyEntry",
Map.of("data-oairecerif_author_affiliation", "OrgUnit_1::"
+ orgUnit_1.getID(),
"oairecerif_author_affiliation", "OrgUnit_1::"
+ orgUnit_1.getID(),
"data-person_identifier_orcid", "",
"person_identifier_orcid", "")),
+ orgUnit_1.getID())),
ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_3.getID().toString(),
"Author 3", "Author 3", "vocabularyEntry",
Map.of("data-oairecerif_author_affiliation", "OrgUnit_2::"
+ orgUnit_2.getID(),
"oairecerif_author_affiliation", "OrgUnit_2::"
+ orgUnit_2.getID(),
"data-person_identifier_orcid", "",
"person_identifier_orcid", ""))
+ orgUnit_2.getID()))
)))
.andExpect(jsonPath("$.page.totalElements", Matchers.is(3)));
}
@Test
public void alternativeNamesAuthorityTest() throws Exception {
context.turnOffAuthorisationSystem();

parentCommunity = CommunityBuilder.createCommunity(context).build();
Collection col1 = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Test collection")
.build();

Item orgUnit_1 = ItemBuilder.createItem(context, col1)
.withTitle("OrgUnit_1")
.withEntityType("orgunit")
.build();

Item author_1 = ItemBuilder.createItem(context, col1)
.withTitle("Author 1")
.withVariantName("Author Variant")
.withEntityType("person")
.withPersonMainAffiliation(orgUnit_1.getName(), orgUnit_1.getID().toString())
.build();

Item author_2 = ItemBuilder.createItem(context, col1)
.withTitle("Author 2")
.withVariantName("Author 2 Variant")
.withPersonMainAffiliation(orgUnit_1.getName(), orgUnit_1.getID().toString())
.withEntityType("person")
.build();

Item author_3 = ItemBuilder.createItem(context, col1)
.withTitle("Author 3")
.withPersonMainAffiliation(orgUnit_1.getName(), orgUnit_1.getID().toString())
.withEntityType("person")
.build();

context.restoreAuthSystemState();
String author1Alternatives = "Author 1::" + author_1.getID() + "|||Author Variant::" + author_1.getID();
Map<String,String> author1Extras = Map.of(
"data-oairecerif_author_affiliation", "OrgUnit_1::" + orgUnit_1.getID(),
"oairecerif_author_affiliation", "OrgUnit_1::" + orgUnit_1.getID(),
"alternative-names", author1Alternatives);
String author2Alternatives = "Author 2::" + author_2.getID() + "|||Author 2 Variant::" + author_2.getID();
Map<String,String> author2Extras = Map.of(
"data-oairecerif_author_affiliation", "OrgUnit_1::" + orgUnit_1.getID(),
"oairecerif_author_affiliation", "OrgUnit_1::" + orgUnit_1.getID(),
"alternative-names", author2Alternatives);
String token = getAuthToken(eperson.getEmail(), password);
getClient(token).perform(get("/api/submission/vocabularies/AuthorAuthority/entries")
.param("metadata", "dc.contributor.author")
.param("collection", col1.getID().toString())
.param("filter", "author"))
.andExpect(status().isOk())
.andExpect(jsonPath("$._embedded.entries", Matchers.containsInAnyOrder(
ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_1.getID().toString(),
"Author 1", "Author 1", "vocabularyEntry", author1Extras),
ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_2.getID().toString(),
"Author 2", "Author 2", "vocabularyEntry", author2Extras),
ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_3.getID().toString(),
"Author 3", "Author 3", "vocabularyEntry", Map.of(
"data-oairecerif_author_affiliation", "OrgUnit_1::" + orgUnit_1.getID(),
"oairecerif_author_affiliation", "OrgUnit_1::" + orgUnit_1.getID()))
)))
.andExpect(jsonPath("$.page.totalElements", Matchers.is(3)));
}
Expand Down Expand Up @@ -224,10 +281,10 @@ public void multiItemAuthorityTest() throws Exception {
"oairecerif_author_affiliation", "OrgUnit_2::" + orgUnit_2.getID())),
ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_1.getID().toString(),
"Author 1", "Author 1", "vocabularyEntry",
Map.of("data-person_identifier_orcid", "", "person_identifier_orcid", "")),
Map.of()),
ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_2.getID().toString(),
"Author 2", "Author 2", "vocabularyEntry",
Map.of("data-person_identifier_orcid", "", "person_identifier_orcid", "")),
Map.of()),
// filled with EditorAuthority extra metadata generator
ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_1.getID().toString(),
"Author 1", "Author 1", "vocabularyEntry", Map.of()),
Expand Down Expand Up @@ -262,9 +319,7 @@ public void singleItemAuthorityWithoutOrgUnitTest() throws Exception {
.andExpect(jsonPath("$._embedded.entries", Matchers.contains(
ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(author_1.getID().toString(),
"Author 1", "Author 1", "vocabularyEntry",
Map.of("data-oairecerif_author_affiliation", "", "oairecerif_author_affiliation", "",
"data-person_identifier_orcid", "",
"person_identifier_orcid", ""))
Map.of())
)))
.andExpect(jsonPath("$.page.totalElements", Matchers.is(1)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -770,11 +770,10 @@ private Item buildPerson(String title, Item affiliation) {

private Matcher<? super Object> affiliationEntry(Item item, String title, String otherInfoValue) {
return ItemAuthorityMatcher.matchItemAuthorityWithOtherInformations(id(item), title,
title, "vocabularyEntry", Map.of(
"data-oairecerif_author_affiliation", otherInfoValue,
"oairecerif_author_affiliation", otherInfoValue,
"data-" + ORCID_INFO, "",
ORCID_INFO, ""));
title, "vocabularyEntry",
otherInfoValue.equals("") ? Map.of() :
Map.of("data-oairecerif_author_affiliation", otherInfoValue,
"oairecerif_author_affiliation", otherInfoValue));
}

private Matcher<? super Object> orcidEntry(String title, String authorityPrefix, String orcid) {
Expand Down
Loading

0 comments on commit a33a12b

Please sign in to comment.