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

metadata-added-provenance #730

Open
wants to merge 54 commits into
base: dtq-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
54 commits
Select commit Hold shift + click to select a range
380fb45
added provenance metadata for update, remove and add
Paurikova2 Aug 13, 2024
ffe630a
checkstyle violations
Paurikova2 Aug 14, 2024
46335a1
added provenance metadata for update and remove bitstream
Paurikova2 Aug 14, 2024
96158a5
item test json added metadata provenance
Paurikova2 Aug 14, 2024
9d6097f
removed unwanted lines
Paurikova2 Aug 14, 2024
a0c500a
control provenance only by tests of item
Paurikova2 Aug 15, 2024
c79c000
update and remove license
Paurikova2 Aug 19, 2024
c55d418
provenance access control and upload bitstream
Paurikova2 Aug 20, 2024
499aac4
provenance move item to different collection
Paurikova2 Aug 20, 2024
9c361d9
provenance make item non-discoverable
Paurikova2 Aug 20, 2024
9f94913
checkstyle violations and test failures
Paurikova2 Aug 21, 2024
2a0d919
make code more readable
Paurikova2 Aug 21, 2024
1922907
provenance for mapped collection
Paurikova2 Aug 22, 2024
d9dd689
grammer check
Paurikova2 Aug 22, 2024
5cddf35
don't write provenance for bitstream without item
Paurikova2 Aug 22, 2024
4a6072a
move addProvenance to parent class
Paurikova2 Aug 22, 2024
e468c90
refactoring
Paurikova2 Aug 22, 2024
9910c90
checkstyle violations and test failures
Paurikova2 Aug 22, 2024
18607a5
removed unnecessary variables, added logs and checkstyle
Paurikova2 Sep 10, 2024
aae82cc
separated class for provenance
Paurikova2 Sep 25, 2024
0b3c0d7
create class for provenance management
Paurikova2 Sep 27, 2024
64d84a1
added metadata item and bitstream tests
Paurikova2 Oct 1, 2024
7c8f7e5
tests for metadata provenance
Paurikova2 Oct 2, 2024
43c5eb2
problem with access control test
Paurikova2 Oct 2, 2024
b67b4b3
tests do not work
Paurikova2 Oct 2, 2024
d7a270b
better service management:
Paurikova2 Oct 7, 2024
e4da4e1
delete clarin license mapping
Paurikova2 Oct 7, 2024
5b6168c
checkstyle violations
Paurikova2 Oct 7, 2024
a4bc467
checkstyle violations
Paurikova2 Oct 7, 2024
0e4c9a2
checkstyle violations
Paurikova2 Oct 7, 2024
556c3d4
checkstyle violations
Paurikova2 Oct 7, 2024
e7caf0d
checkstyle violations
Paurikova2 Oct 7, 2024
9b7fb5c
added json to resources
Paurikova2 Oct 7, 2024
eba6bbd
modified provenance patch messages
Paurikova2 Oct 7, 2024
a0d5d55
messages bags
Paurikova2 Oct 7, 2024
5282d63
refactoring based on git comparison
Paurikova2 Oct 7, 2024
828769f
checkstyle violations
Paurikova2 Oct 7, 2024
a1b95e6
used correct json
Paurikova2 Oct 8, 2024
8621bcd
checkstyle violations
Paurikova2 Oct 8, 2024
2fdc96e
log exception, replace ! by non conds, added doc comments
Paurikova2 Oct 10, 2024
b026ca0
added logs for replacing mtd
Paurikova2 Oct 17, 2024
64d7eae
removed unused services
Paurikova2 Nov 20, 2024
49cae22
make object from provenance service
Paurikova2 Nov 22, 2024
eb2315e
removed interface prom provenance msg provider
Paurikova2 Nov 22, 2024
876a7f2
checkstyle
Paurikova2 Nov 22, 2024
130d78f
Refactored method `removeReadPolicies` - add provenance after removin…
milanmajchrak Dec 12, 2024
419aff3
The message templates are loaded from the Enum instead of json file.
milanmajchrak Dec 12, 2024
a0abf72
The `getMessage` methods was overloaded.
milanmajchrak Dec 13, 2024
a1324ce
Renamed `getItem` to `findItemByBitstream` to clarify the method's pu…
milanmajchrak Dec 13, 2024
8ff24e0
Do not throw exception when adding to provenance
milanmajchrak Dec 13, 2024
51302fa
The exceptions are caught in the ProvenanceProvider and changed order…
milanmajchrak Dec 13, 2024
46ab18c
Renamed ProvenanceProvider to ProvenanceService and refactored it to …
milanmajchrak Dec 13, 2024
5f63dcd
The ProvenanceService wasn't initialized in the BundleAccessControl
milanmajchrak Dec 16, 2024
fb82e94
Removal of unwanted changes
milanmajchrak Dec 16, 2024
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
Expand Up @@ -55,6 +55,8 @@
import org.dspace.content.service.ItemService;
import org.dspace.core.Constants;
import org.dspace.core.Context;
import org.dspace.core.ProvenanceService;
import org.dspace.core.factory.CoreServiceFactory;
import org.dspace.discovery.DiscoverQuery;
import org.dspace.discovery.SearchService;
import org.dspace.discovery.SearchServiceException;
Expand Down Expand Up @@ -111,6 +113,8 @@ public class BulkAccessControl extends DSpaceRunnable<BulkAccessControlScriptCon

protected String eperson = null;

protected ProvenanceService provenanceService;

@Override
@SuppressWarnings("unchecked")
public void setup() throws ParseException {
Expand Down Expand Up @@ -143,6 +147,7 @@ public void setup() throws ParseException {
help = commandLine.hasOption('h');
filename = commandLine.getOptionValue('f');
uuids = commandLine.hasOption('u') ? Arrays.asList(commandLine.getOptionValues('u')) : null;
this.provenanceService = CoreServiceFactory.getInstance().getProvenanceService();
}

@Override
Expand Down Expand Up @@ -465,6 +470,8 @@ private void setItemPolicies(Item item, BulkAccessControlInput accessControl)
itemAccessConditions.get(accessCondition.getName())));

itemService.adjustItemPolicies(context, item, item.getOwningCollection(), false);

provenanceService.setItemPolicies(context, item, accessControl);
}

/**
Expand Down Expand Up @@ -552,6 +559,10 @@ private void updateBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessC
*/
private void removeReadPolicies(DSpaceObject dso, String type) {
try {
String resPoliciesStr = provenanceService.removedReadPolicies(context, dso, type);
if (Objects.isNull(resPoliciesStr)) {
return;
}
resourcePolicyService.removePolicies(context, dso, type, Constants.READ);
} catch (SQLException | AuthorizeException e) {
throw new BulkAccessControlException(e);
Expand Down Expand Up @@ -580,6 +591,7 @@ private void setBitstreamPolicies(Bitstream bitstream, Item item, BulkAccessCont

itemService.adjustBitstreamPolicies(context, item, item.getOwningCollection(), bitstream);
mediaFilterService.updatePoliciesOfDerivativeBitstreams(context, item, bitstream);
provenanceService.setBitstreamPolicies(context, bitstream, item, accessControl);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* 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.core;

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

import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.content.Bitstream;
import org.dspace.content.Item;
import org.dspace.content.MetadataField;

/**
* Interface for providing provenance messages.
Paurikova2 marked this conversation as resolved.
Show resolved Hide resolved
*
* @author Michaela Paurikova (dspace at dataquest.sk)
*/
public interface ProvenanceMessageProvider {
public String getMessage(Context context, String templateKey, Object... args)
throws SQLException, AuthorizeException;
public String getMessage(Context context, String templateKey, Item item, Object... args)
throws SQLException, AuthorizeException;
public String getMessage(String templateKey, Object... args);
public String addCollectionsToMessage(Item item);
public String getBitstreamMessage(Bitstream bitstream);
public String getResourcePoliciesMessage(List<ResourcePolicy> resPolicies);
public String getMetadata(String oldMtdKey, String oldMtdValue);
public String getMetadataField(MetadataField metadataField);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
/**
* 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.core;

import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.dspace.authorize.AuthorizeException;
import org.dspace.authorize.ResourcePolicy;
import org.dspace.content.Bitstream;
import org.dspace.content.Collection;
import org.dspace.content.DCDate;
import org.dspace.content.Item;
import org.dspace.content.MetadataField;
import org.dspace.content.factory.ContentServiceFactory;
import org.dspace.content.service.InstallItemService;
import org.dspace.eperson.EPerson;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Paurikova2 marked this conversation as resolved.
Show resolved Hide resolved
/**
* The ProvenanceMessageProviderImpl class implements the ProvenanceMessageProvider interface,
* providing methods to generate provenance messages for DSpace items. It loads message templates
* from a JSON file and formats messages based on the context, including user details and timestamps.
*
* @author Michaela Paurikova (dspace at dataquest.sk)
*/
public class ProvenanceMessageProviderImpl implements ProvenanceMessageProvider {
private static final String PROVENANCE_MSG_JSON = "provenance_messages.json";
private static final Logger log = LoggerFactory.getLogger(ProvenanceMessageProviderImpl.class);
private Map<String, String> messageTemplates;
private InstallItemService installItemService = ContentServiceFactory.getInstance().getInstallItemService();

public ProvenanceMessageProviderImpl() {
loadMessageTemplates();
}

private void loadMessageTemplates() {
ObjectMapper mapper = new ObjectMapper();
String msg;
try (InputStream inputStream = getClass().getResourceAsStream(PROVENANCE_MSG_JSON)) {
if (inputStream == null) {
msg = "Failed to find message templates file.";
log.error(msg);
throw new RuntimeException(msg);
}
messageTemplates = mapper.readValue(inputStream, Map.class);
} catch (IOException e) {
msg = "Failed to load message templates.";
log.error(msg);
throw new RuntimeException(msg, e);
}
}

@Override
public String getMessage(Context context, String templateKey, Item item, Object... args)
throws SQLException, AuthorizeException {
String msg = getMessage(context, templateKey, args);
msg = msg + "\n" + installItemService.getBitstreamProvenanceMessage(context, item);
return msg;
}

@Override
public String getMessage(String templateKey, Object... args) {
String template = messageTemplates.get(templateKey);
if (template == null) {
throw new IllegalArgumentException("No message template found for key: " + templateKey);
}
return String.format(template, args);
}

@Override
public String getMessage(Context context, String templateKey, Object... args) {
EPerson currentUser = context.getCurrentUser();
String timestamp = DCDate.getCurrent().toString();
String details = getMessage(templateKey, args);
return String.format("%s by %s (%s) on %s",
details,
currentUser.getFullName(),
currentUser.getEmail(),
timestamp);
}

@Override
public String addCollectionsToMessage(Item item) {
String msg = "Item was in collections:\n";
List<Collection> collsList = item.getCollections();
for (Collection coll : collsList) {
msg = msg + coll.getName() + " (ID: " + coll.getID() + ")\n";
}
return msg;
}

@Override
public String getBitstreamMessage(Bitstream bitstream) {
// values of deleted bitstream
String msg = bitstream.getName() + ": " +
bitstream.getSizeBytes() + " bytes, checksum: " +
bitstream.getChecksum() + " (" +
bitstream.getChecksumAlgorithm() + ")\n";
return msg;
}

@Override
public String getResourcePoliciesMessage(List<ResourcePolicy> resPolicies) {
return resPolicies.stream()
.filter(rp -> rp.getAction() == Constants.READ)
.map(rp -> String.format("[%s, %s, %d, %s, %s, %s, %s]",
rp.getRpName(), rp.getRpType(), rp.getAction(),
rp.getEPerson() != null ? rp.getEPerson().getEmail() : null,
rp.getGroup() != null ? rp.getGroup().getName() : null,
rp.getStartDate() != null ? rp.getStartDate().toString() : null,
rp.getEndDate() != null ? rp.getEndDate().toString() : null))
.collect(Collectors.joining(";"));
}

@Override
public String getMetadata(String oldMtdKey, String oldMtdValue) {
return oldMtdKey + ": " + oldMtdValue;
}

@Override
public String getMetadataField(MetadataField metadataField) {
return metadataField.toString()
.replace('_', '.');
}
}
58 changes: 58 additions & 0 deletions dspace-api/src/main/java/org/dspace/core/ProvenanceService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* 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.core;

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

import org.dspace.app.bulkaccesscontrol.model.BulkAccessControlInput;
import org.dspace.authorize.AuthorizeException;
import org.dspace.content.Bitstream;
import org.dspace.content.Bundle;
import org.dspace.content.Collection;
import org.dspace.content.DSpaceObject;
import org.dspace.content.Item;
import org.dspace.content.MetadataField;
import org.dspace.content.MetadataValue;

/**
* The ProvenanceService interface defines methods for creating provenance metadata
* for items based on the actions performed.
*
* @author Michaela Paurikova (dspace at dataquest.sk)
*/
public interface ProvenanceService {
Paurikova2 marked this conversation as resolved.
Show resolved Hide resolved
public void setBitstreamPolicies(Context context, Bitstream bitstream, Item item,
BulkAccessControlInput accessControl) throws SQLException, AuthorizeException;

public void setItemPolicies(Context context, Item item, BulkAccessControlInput accessControl)
throws SQLException, AuthorizeException;

public String removedReadPolicies(Context context, DSpaceObject dso, String type)
throws SQLException, AuthorizeException;
public void uploadBitstream(Context context, Bundle bundle) throws SQLException, AuthorizeException;
public void editLicense(Context context, Item item, boolean newLicense) throws SQLException, AuthorizeException;

public void moveItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException;
public void mappedItem(Context context, Item item, Collection collection) throws SQLException, AuthorizeException;
public void deletedItemFromMapped(Context context, Item item, Collection collection)
throws SQLException, AuthorizeException;
public void deleteBitstream(Context context,Bitstream bitstream) throws SQLException, AuthorizeException;
public void addMetadata(Context context, DSpaceObject dso, MetadataField metadataField)
throws SQLException, AuthorizeException;
public void removeMetadata(Context context, DSpaceObject dso, MetadataField metadataField)
throws SQLException, AuthorizeException;
public void removeMetadataAtIndex(Context context, DSpaceObject dso, List<MetadataValue> metadataValues,
int indexInt) throws SQLException, AuthorizeException;
public void replaceMetadata(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal)
throws SQLException, AuthorizeException;
public void replaceMetadataSingle(Context context, DSpaceObject dso, MetadataField metadataField, String oldMtdVal)
throws SQLException, AuthorizeException;
public void makeDiscoverable(Context context, Item item, boolean discoverable)
throws SQLException, AuthorizeException;
}
Loading
Loading