Added allow-bulk-deletion property to specify erasable fields via bulk deletion

This commit is contained in:
Luca Giamminonni
2021-03-26 15:37:49 +01:00
parent 233202dbe4
commit d421ac1b63
5 changed files with 209 additions and 18 deletions

View File

@@ -10,12 +10,15 @@ package org.dspace.app.bulkedit;
import java.sql.SQLException;
import org.apache.commons.cli.ParseException;
import org.apache.commons.lang3.ArrayUtils;
import org.dspace.content.MetadataField;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.MetadataFieldService;
import org.dspace.content.service.MetadataValueService;
import org.dspace.core.Context;
import org.dspace.scripts.DSpaceRunnable;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.dspace.utils.DSpace;
/**
@@ -27,38 +30,65 @@ import org.dspace.utils.DSpace;
*/
public class MetadataDeletion extends DSpaceRunnable<MetadataDeletionScriptConfiguration<MetadataDeletion>> {
private MetadataValueService metadataValueService;
private MetadataFieldService metadataFieldService;
private ConfigurationService configurationService;
private String metadataField;
private boolean list;
@Override
public void internalRun() throws Exception {
Context context = new Context();
context.turnOffAuthorisationSystem();
try {
performMetadataValuesDeletion(context);
} catch (SQLException e) {
handler.handleException(e);
if (list) {
listErasableMetadata();
return;
}
context.restoreAuthSystemState();
context.complete();
Context context = new Context();
try {
context.turnOffAuthorisationSystem();
performMetadataValuesDeletion(context);
} finally {
context.restoreAuthSystemState();
context.complete();
}
}
private void listErasableMetadata() {
String[] erasableMetadata = getErasableMetadata();
if (ArrayUtils.isEmpty(erasableMetadata)) {
handler.logInfo("No fields has been configured to be cleared via bulk deletion");
} else {
handler.logInfo("The fields that can be bulk deleted are: " + String.join(", ", erasableMetadata));
}
}
private void performMetadataValuesDeletion(Context context) throws SQLException {
MetadataValueService metadataValueService = ContentServiceFactory.getInstance()
.getMetadataValueService();
MetadataFieldService metadataFieldService = ContentServiceFactory.getInstance()
.getMetadataFieldService();
MetadataField field = metadataFieldService.findByString(context, metadataField, '.');
if (field == null) {
throw new IllegalArgumentException("No metadata field found with name " + metadataField);
}
if (!ArrayUtils.contains(getErasableMetadata(), metadataField)) {
throw new IllegalArgumentException("The given metadata field cannot be bulk deleted");
}
handler.logInfo(String.format("Deleting the field '%s' from all objects", metadataField));
metadataValueService.deleteByMetadataField(context, field);
}
private String[] getErasableMetadata() {
return configurationService.getArrayProperty("bulkedit.allow-bulk-deletion");
}
@Override
@SuppressWarnings("unchecked")
public MetadataDeletionScriptConfiguration<MetadataDeletion> getScriptConfiguration() {
@@ -68,7 +98,18 @@ public class MetadataDeletion extends DSpaceRunnable<MetadataDeletionScriptConfi
@Override
public void setup() throws ParseException {
metadataValueService = ContentServiceFactory.getInstance().getMetadataValueService();
metadataFieldService = ContentServiceFactory.getInstance().getMetadataFieldService();
configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
metadataField = commandLine.getOptionValue('m');
list = commandLine.hasOption('l');
if (!list && metadataField == null) {
throw new ParseException("One of the following parameters is required: -m or -l");
}
}
}

View File

@@ -37,9 +37,15 @@ public class MetadataDeletionScriptConfiguration<T extends MetadataDeletion> ext
@Override
public Options getOptions() {
if (options == null) {
Options options = new Options();
options.addOption("m", "metadata", true, "metadata field name");
options.getOption("m").setType(String.class);
options.addOption("l", "list", false, "lists the metadata fields that can be deleted");
options.getOption("l").setType(boolean.class);
super.options = options;
}
return options;

View File

@@ -7,8 +7,17 @@
*/
package org.dspace.app.bulkedit;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.empty;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasItem;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.dspace.AbstractIntegrationTestWithDatabase;
import org.dspace.app.launcher.ScriptLauncher;
@@ -22,6 +31,9 @@ import org.dspace.content.MetadataField;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.MetadataFieldService;
import org.dspace.content.service.MetadataValueService;
import org.dspace.services.ConfigurationService;
import org.dspace.services.factory.DSpaceServicesFactory;
import org.junit.Before;
import org.junit.Test;
/**
@@ -36,15 +48,100 @@ public class MetadataDeletionIT extends AbstractIntegrationTestWithDatabase {
private MetadataFieldService metadataFieldService = ContentServiceFactory.getInstance().getMetadataFieldService();
@Test
public void metadataDeletionTest() throws Exception {
private ConfigurationService configurationService = DSpaceServicesFactory.getInstance().getConfigurationService();
@Before
public void setup() {
context.turnOffAuthorisationSystem();
Community community = CommunityBuilder.createCommunity(context).build();
Collection collection = CollectionBuilder.createCollection(context, community).build();
createItem(collection, "My First publication", "Mario Rossi");
createItem(collection, "Another publication", "John Smith");
context.restoreAuthSystemState();
}
@Test
public void metadataDeletionListTest() throws Exception {
configurationService.setProperty("bulkedit.allow-bulk-deletion", new String[] { "dc.title", "dc.type" });
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
String[] args = new String[] { "metadata-deletion", "-l" };
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
List<String> infoMessages = testDSpaceRunnableHandler.getInfoMessages();
assertThat(infoMessages, hasSize(1));
assertThat(infoMessages, hasItem(equalTo("The fields that can be bulk deleted are: dc.title, dc.type")));
}
@Test
public void metadataDeletionListWithoutErasableMetadataTest() throws Exception {
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
String[] args = new String[] { "metadata-deletion", "-l" };
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
List<String> infoMessages = testDSpaceRunnableHandler.getInfoMessages();
assertThat(infoMessages, hasSize(1));
assertThat(infoMessages, hasItem(equalTo("No fields has been configured to be cleared via bulk deletion")));
}
@Test
public void metadataDeletionTest() throws Exception {
MetadataField titleField = metadataFieldService.findByElement(context, "dc", "title", null);
MetadataField authorField = metadataFieldService.findByElement(context, "dc", "contributor", "author");
assertThat(metadataValueService.findByField(context, titleField), hasSize(2));
assertThat(metadataValueService.findByField(context, authorField), hasSize(2));
configurationService.setProperty("bulkedit.allow-bulk-deletion", "dc.title");
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
String[] args = new String[] { "metadata-deletion", "-m", "dc.title" };
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
assertThat(metadataValueService.findByField(context, titleField), empty());
assertThat(metadataValueService.findByField(context, authorField), hasSize(2));
List<String> infoMessages = testDSpaceRunnableHandler.getInfoMessages();
assertThat(infoMessages, hasSize(1));
assertThat(infoMessages, hasItem(equalTo("Deleting the field 'dc.title' from all objects")));
}
@Test
public void metadataDeletionNotAllowedTest() throws Exception {
MetadataField titleField = metadataFieldService.findByElement(context, "dc", "title", null);
MetadataField authorField = metadataFieldService.findByElement(context, "dc", "contributor", "author");
assertEquals(2, metadataValueService.findByField(context, titleField).size());
assertEquals(2, metadataValueService.findByField(context, authorField).size());
configurationService.setProperty("bulkedit.allow-bulk-deletion", "dc.type");
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
String[] args = new String[] { "metadata-deletion", "-m", "dc.title" };
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
Exception exception = testDSpaceRunnableHandler.getException();
assertThat(exception, notNullValue());
assertThat(exception, instanceOf(IllegalArgumentException.class));
assertThat(exception.getMessage(), is("The given metadata field cannot be bulk deleted"));
assertEquals(2, metadataValueService.findByField(context, titleField).size());
assertEquals(2, metadataValueService.findByField(context, authorField).size());
}
@Test
public void metadataDeletionWithUnknownMetadataTest() throws Exception {
MetadataField titleField = metadataFieldService.findByElement(context, "dc", "title", null);
MetadataField authorField = metadataFieldService.findByElement(context, "dc", "contributor", "author");
@@ -54,10 +151,15 @@ public class MetadataDeletionIT extends AbstractIntegrationTestWithDatabase {
TestDSpaceRunnableHandler testDSpaceRunnableHandler = new TestDSpaceRunnableHandler();
String[] args = new String[] { "metadata-deletion", "-m", "dc.title" };
String[] args = new String[] { "metadata-deletion", "-m", "dc.unknown" };
ScriptLauncher.handleScript(args, ScriptLauncher.getConfig(kernelImpl), testDSpaceRunnableHandler, kernelImpl);
assertTrue(metadataValueService.findByField(context, titleField).isEmpty());
Exception exception = testDSpaceRunnableHandler.getException();
assertThat(exception, notNullValue());
assertThat(exception, instanceOf(IllegalArgumentException.class));
assertThat(exception.getMessage(), is("No metadata field found with name dc.unknown"));
assertEquals(2, metadataValueService.findByField(context, titleField).size());
assertEquals(2, metadataValueService.findByField(context, authorField).size());
}

View File

@@ -7,6 +7,9 @@
*/
package org.dspace.app.scripts.handler.impl;
import java.util.ArrayList;
import java.util.List;
import org.dspace.scripts.handler.impl.CommandLineDSpaceRunnableHandler;
/**
@@ -17,6 +20,12 @@ public class TestDSpaceRunnableHandler extends CommandLineDSpaceRunnableHandler
private Exception exception = null;
private final List<String> infoMessages = new ArrayList<>();
private final List<String> errorMessages = new ArrayList<>();
private final List<String> warningMessages = new ArrayList<>();
/**
* We're overriding this method so that we can stop the script from doing the System.exit() if
* an exception within the script is thrown
@@ -33,4 +42,34 @@ public class TestDSpaceRunnableHandler extends CommandLineDSpaceRunnableHandler
public Exception getException() {
return exception;
}
@Override
public void logInfo(String message) {
super.logInfo(message);
infoMessages.add(message);
}
@Override
public void logWarning(String message) {
super.logWarning(message);
warningMessages.add(message);
}
@Override
public void logError(String message) {
super.logError(message);
errorMessages.add(message);
}
public List<String> getInfoMessages() {
return infoMessages;
}
public List<String> getErrorMessages() {
return errorMessages;
}
public List<String> getWarningMessages() {
return warningMessages;
}
}

View File

@@ -1488,6 +1488,9 @@ mail.helpdesk.name = Help Desk
# Should all Request Copy emails go to the helpdesk instead of the item submitter?
request.item.helpdesk.override = false
### metadata-deletion script configuration ###
bulkedit.allow-bulk-deletion = dspace.agreements.end-user
#------------------------------------------------------------------#
#-------------------MODULE CONFIGURATIONS--------------------------#