Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Enhancement nameenhancer #441

Draft
wants to merge 2 commits into
base: main-cris
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/**
* 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.content.enhancer.impl;

import java.sql.SQLException;
import java.util.List;
import java.util.Objects;

import org.apache.commons.lang.StringUtils;
import org.dspace.content.Item;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataValue;
import org.dspace.content.enhancer.AbstractItemEnhancer;
import org.dspace.content.enhancer.ItemEnhancer;
import org.dspace.content.service.ItemService;
import org.dspace.content.service.MetadataFieldService;
import org.dspace.core.Context;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

/**
* Implementation of {@link ItemEnhancer} that add metadata values on the given
* item from a list of other metadatavalues .
* The first value of the list that is not null matches and overwrites the existing value.
* Some default value can be specified if no fields were found
*
* @author Florian Gantner ([email protected])
*
*/
public class NameEnhancer extends AbstractItemEnhancer {

private static final Logger LOGGER = LoggerFactory.getLogger(NameEnhancer.class);

@Autowired
private ItemService itemService;

@Autowired
private MetadataFieldService metadatafieldService;

private String sourceEntityType;

private String targetItemMetadataField;

private List<String> relatedItemMetadataFields;
private String defaultValue;

@Override
public boolean canEnhance(Context context, Item item) {
return sourceEntityType == null || sourceEntityType.equals(itemService.getEntityType(item));
}

@Override
public boolean enhance(Context context, Item item, boolean deepMode) {
try {
if (Objects.isNull(relatedItemMetadataFields) || relatedItemMetadataFields.isEmpty() ||
StringUtils.isBlank(targetItemMetadataField)) {
return false;
}
return checkNames(context, item, deepMode);
} catch (Exception e) {
LOGGER.error("An error occurs enhancing item with id {}: {}", item.getID(), e.getMessage(), e);
//Exception handling not supported by ItemEnhancerService. Thus, just log to continue other enhancers
//throw new SQLRuntimeException(e);
}
return false;
}

/**
* Check the names/values from the specified metadatafield and compare the first value found
* with the target metadatafield. Updates the target metadatafield when the value is different
* or when deepMode is set.
* When the target metadatafield has not been set before, then set this value.
* @param context current Context
* @param item current item
* @param deepMode boolean
* @return boolean value if some change/update has happened
* @throws Exception when some error occurs
*/
private boolean checkNames(Context context, Item item, boolean deepMode) throws Exception {
// ignore languages of Metadata here. Assume main title is not repeated
// Could be more simplified
List<MetadataValue> currentnames = itemService.getMetadataByMetadataString(item, targetItemMetadataField);

if (!currentnames.isEmpty()) {
// some name is assigned yet
for (MetadataValue currentname : currentnames) {
String val = currentname.getValue();
for (String field : relatedItemMetadataFields) {
List<MetadataValue> fieldnames =
itemService.getMetadataByMetadataString(item, field);
if (fieldnames.isEmpty()) {
continue ; //No Values, try next loop
}
for (MetadataValue fieldname : fieldnames) {
if (StringUtils.isNotBlank(fieldname.getValue())
&& fieldname.getValue().contentEquals(val)) {
//Values are the same. No Update necessary
if (deepMode) {
// value is recalculated in deepMode
return updateTargetMetadata(context, item, fieldname.getValue(), true);
}
return false;
} else {
//values differ. We must update the value
return updateTargetMetadata(context, item, fieldname.getValue(), true);
}
}
}
}
if (StringUtils.isNotBlank(defaultValue)
&& !currentnames.get(0).getValue().contentEquals(defaultValue)) {
// None of the names above matches. Set Default-Value, if it exists. Otherwise, do nothing
return updateTargetMetadata(context, item, defaultValue, true);
}

} else {
// No Name assigned yet
// Check existing names
for (String field : relatedItemMetadataFields) {
List<MetadataValue> fieldnames = itemService.getMetadataByMetadataString(item, field);
if (fieldnames.isEmpty()) {
continue; //No Values, try next loop
}
for (MetadataValue fieldname : fieldnames) {
if (StringUtils.isNotBlank(fieldname.getValue())) {
//Got some value
return updateTargetMetadata(context, item, fieldname.getValue(), false);
}
}
}
// If no name exist, set defaultvalue
if (StringUtils.isNotBlank(defaultValue)) {
return updateTargetMetadata(context, item, defaultValue, false);
}
// otherwise do not assign any value
}
return false;
}

/**
* Update/Set the target metadata with option to clear/delete previous metadatavalues
* @param context current Context
* @param item item to set metadatavalue
* @param value value to set
* @param clear clear/delete existing values byfore
* @return boolean value if the value has been updated successfully
* @throws SQLException when some error occurs
*/
private boolean updateTargetMetadata(Context context, Item item, String value, boolean clear) throws SQLException {
MetadataField targetmd = metadatafieldService.findByString(context, targetItemMetadataField, '.');
if (targetmd != null) {
if (clear) {
itemService.clearMetadata(context, item, targetmd.getMetadataSchema().getName(), targetmd.getElement(),
targetmd.getQualifier(), Item.ANY);
}
itemService.addMetadata(context, item, targetmd, null, value);
return true;
} else {
LOGGER.error("No valid metadatavalue to enhance specified");
}
return false;
}

public void setSourceEntityType(String sourceEntityType) {
this.sourceEntityType = sourceEntityType;
}

public void setTargetItemMetadataField(String targetItemMetadataField) {
this.targetItemMetadataField = targetItemMetadataField;
}

public void setRelatedItemMetadataFields(List<String> relatedItemMetadataFields) {
this.relatedItemMetadataFields = relatedItemMetadataFields;
}

public void setDefaultValue(String defaultvalue) {
this.defaultValue = defaultvalue;
}

}

Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ public class ItemEnhancerScriptIT extends AbstractIntegrationTestWithDatabase {

private Collection collection;

private Collection persons;

/**
* This method will be run before the first test as per @BeforeClass. It will
Expand Down Expand Up @@ -100,6 +101,12 @@ public void setup() {
collection = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection")
.build();

persons = CollectionBuilder.createCollection(context, parentCommunity)
.withName("Collection")
.withEntityType("Person")
.build();

context.restoreAuthSystemState();

}
Expand Down Expand Up @@ -321,6 +328,70 @@ public void testItemEnhancementWithForce() throws Exception {

}

@Test
public void testItemEnhancementNameWithoutForce() throws Exception {

context.turnOffAuthorisationSystem();

Item firstPerson = ItemBuilder.createItem(context, persons)
.withMetadata("crisrp", "name", null, "Walter White")
.build();

Item secondPerson = ItemBuilder.createItem(context, persons)
.withMetadata("crisrp", "name", null, "Alois White")
.withMetadata("crisrp", "name", "translated", "Alois W. White")
.build();

Item thirdPerson = ItemBuilder.createItem(context, persons)
.withMetadata("crisrp", "name", "translated", "Walt Alternative")
.build();

context.commit();


assertThat(getMetadataValues(firstPerson, "dc.title"), empty());
assertThat(getMetadataValues(secondPerson, "dc.title"), empty());
assertThat(getMetadataValues(thirdPerson, "dc.title"), empty());

TestDSpaceRunnableHandler runnableHandler = runScript(false);

assertThat(runnableHandler.getErrorMessages(), empty());
assertThat(runnableHandler.getInfoMessages(), hasItem("Enhancement completed with success"));

firstPerson = reload(firstPerson);
secondPerson = reload(secondPerson);
thirdPerson = reload(thirdPerson);

assertThat(getMetadataValues(firstPerson, "dc.title"), hasSize(1));
assertThat(getMetadataValues(secondPerson, "dc.title"), hasSize(1));
assertThat(getMetadataValues(thirdPerson, "dc.title"), hasSize(1));

assertThat(firstPerson.getMetadata(), hasItem(with("dc.title", "Walter White")));
assertThat(secondPerson.getMetadata(), hasItem(with("dc.title", "Alois White")));
assertThat(thirdPerson.getMetadata(), hasItem(with("dc.title", "Walt Alternative")));

context.turnOffAuthorisationSystem();

MetadataValue nameToRemove = getMetadataValues(secondPerson, "crisrp.name").get(0);
itemService.removeMetadataValues(context, secondPerson, List.of(nameToRemove));

replaceMetadata(thirdPerson, "crisrp", "name", "translated", "Walt D. Alternative");

context.restoreAuthSystemState();

runnableHandler = runScript(false);
assertThat(runnableHandler.getErrorMessages(), empty());
assertThat(runnableHandler.getInfoMessages(), hasItem("Enhancement completed with success"));

firstPerson = reload(firstPerson);
secondPerson = reload(secondPerson);
thirdPerson = reload(thirdPerson);

assertThat(firstPerson.getMetadata(), hasItem(with("dc.title", "Walter White")));
assertThat(secondPerson.getMetadata(), hasItem(with("dc.title", "Alois W. White")));
assertThat(thirdPerson.getMetadata(), hasItem(with("dc.title", "Walt D. Alternative")));
}

@Test
public void testItemEnhancementMetadataPositions() throws Exception {

Expand Down
16 changes: 15 additions & 1 deletion dspace/config/spring/api/metadata-enhancers.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,20 @@
<property name="relatedItemMetadataField" value="person.identifier.orcid" />
<property name="virtualQualifier" value="editor-orcid" />
</bean>


<!-- Set dc.title of person from some of their other name fields -->
<bean class="org.dspace.content.enhancer.impl.NameEnhancer" >
<property name="sourceEntityType" value="Person" />
<property name="targetItemMetadataField" value="dc.title" />
<property name="relatedItemMetadataFields">
<list>
<value>crisrp.name</value>
<value>crisrp.name.translated</value>
<value>crisrp.name.variants</value>
</list>
</property>
<!-- using some defaultValue might not work with creating profiles -->
<!-- <property name="defaultValue" value="N.N." /> -->
</bean>

</beans>
Loading