Skip to content
Merged
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
Expand Up @@ -3,5 +3,3 @@
Dataverse Featured Items can now be linked to Dataverses, Datasets, or Datafiles.

Pre-existing featured items as well as new items without dvObjects will be defaulted to type=custom.

Featured Items with dvObjects will be filtered out of lists if the dvObject should not be viewed (i.e. datafiles that are restricted or datasets that are deaccessioned)
10 changes: 5 additions & 5 deletions doc/sphinx-guides/source/api/native-api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1218,9 +1218,9 @@ The ``file`` parameter must be specified for each image we want to attach to fea

The ``id`` parameter must be ``0`` for new items or set to the item's identifier for updates. The ``fileName`` parameter should be empty to exclude an image or match the name of a file sent in a ``file`` parameter to set a new image. ``keepFile`` must always be set to ``false``, unless it's an update to a featured item where we want to preserve the existing image, if one exists.

The ``type`` and ``dvObject`` parameters are optional. These allow you to link the featured item to a Dataverse, Dataset, or Datafile.
The ``dvObject`` can be passed as the id or the persistent identifier and the ``type`` must be passed as either "dataverse", "dataset", or "datafile", depending on the type of object.
If no ``dvObject`` is passed the ``type`` will default to "custom" designating no linked object.
The ``type`` and ``dvObjectIdentifier`` parameters are optional. These allow you to link the featured item to a Dataverse, Dataset, or Datafile.
The ``dvObjectIdentifier`` can be passed as the alias, id, or the persistent identifier and the ``type`` must be passed as either "dataverse", "dataset", or "datafile", depending on the type of object.
If no ``dvObjectIdentifier`` is passed the ``type`` will default to "custom" designating no linked object.

Note that any existing featured item not included in the call with its associated identifier and corresponding properties will be removed from the collection.

Expand Down Expand Up @@ -1250,7 +1250,7 @@ The following example creates two featured items, with an image and a dataset as
-F "keepFile=false" -F "keepFile=false" \
-F "file=@$SECOND_ITEM_IMAGE_FILENAME" \
-F "type=" -F "type=@$SECOND_ITEM_TYPE" \
-F "dvObject=" -F "dvObject=@$SECOND_ITEM_DVOBJECT" \
-F "dvObjectIdentifier=" -F "dvObjectIdentifier=@$SECOND_ITEM_DVOBJECT" \
"$SERVER_URL/api/dataverses/$ID/featuredItems"


Expand All @@ -1267,7 +1267,7 @@ The fully expanded example above (without environment variables) looks like this
-F "keepFile=false" -F "keepFile=false" \
-F "[email protected]" \
-F "type=" -F "type=dataset" \
-F "dvObject=" -F "dvObject=doi:ZZ7/MOSEISLEYDB94" \
-F "dvObjectIdentifier=" -F "dvObjectIdentifier=doi:ZZ7/MOSEISLEYDB94" \
"https://demo.dataverse.org/api/dataverses/root/featuredItems"

The following example creates one featured item and updates a second one, keeping the existing image it may have had but removes the dataset link and defaults the type to "custom":
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -590,7 +590,14 @@ protected DvObject findDvo(@NotNull final String id) throws WrappedResponse {
protected DvObject findDvoByIdAndFeaturedItemTypeOrDie(@NotNull final String dvIdtf, String type) throws WrappedResponse {
try {
DataverseFeaturedItem.TYPES dvType = DataverseFeaturedItem.getDvType(type);
DvObject dvObject = isNumeric(dvIdtf) ? findDvo(Long.valueOf(dvIdtf)) : null;
DvObject dvObject = null;
if (isNumeric(dvIdtf)) {
try {
dvObject = findDvo(Long.valueOf(dvIdtf));
} catch (Exception e) {
throw new WrappedResponse(error(Response.Status.BAD_REQUEST,BundleUtil.getStringFromBundle("find.dvo.error.dvObjectNotFound", Arrays.asList(dvIdtf))));
}
}
if (dvObject == null) {
List<DataverseFeaturedItem.TYPES> types = new ArrayList<>();
types.addAll(List.of(DataverseFeaturedItem.TYPES.values()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public Response updateFeaturedItem(@Context ContainerRequestContext crc,
@PathParam("id") Long id,
@FormDataParam("content") String content,
@FormDataParam("type") String type,
@FormDataParam("dvObject") String dvObjectIdtf,
@FormDataParam("dvObjectIdentifier") String dvObjectIdtf,
@FormDataParam("displayOrder") int displayOrder,
@FormDataParam("keepFile") boolean keepFile,
@FormDataParam("file") InputStream imageFileInputStream,
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java
Original file line number Diff line number Diff line change
Expand Up @@ -1793,7 +1793,7 @@ public Response getUserPermissionsOnDataverse(@Context ContainerRequestContext c
public Response createFeaturedItem(@Context ContainerRequestContext crc,
@PathParam("identifier") String dvIdtf,
@FormDataParam("type") String type,
@FormDataParam("dvObject") String dvObjectIdtf,
@FormDataParam("dvObjectIdentifier") String dvObjectIdtf,
@FormDataParam("content") String content,
@FormDataParam("displayOrder") int displayOrder,
@FormDataParam("file") InputStream imageFileInputStream,
Expand Down Expand Up @@ -1844,7 +1844,7 @@ public Response updateFeaturedItems(
@FormDataParam("id") List<Long> ids,
@FormDataParam("content") List<String> contents,
@FormDataParam("type") List<String> types,
@FormDataParam("dvObject") List<String> dvObjectIdtf,
@FormDataParam("dvObjectIdentifier") List<String> dvObjectIdtf,
@FormDataParam("displayOrder") List<Integer> displayOrders,
@FormDataParam("keepFile") List<Boolean> keepFiles,
@FormDataParam("fileName") List<String> fileNames,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Min;
import jakarta.validation.constraints.Size;
import org.apache.commons.text.CaseUtils;

import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -144,6 +145,17 @@ public static void validateTypeAndDvObject(String dvIdtf, DvObject dvObject, Dat
(dvObject instanceof DataFile && dvType != DataverseFeaturedItem.TYPES.DATAFILE)) {
throw new IllegalArgumentException(BundleUtil.getStringFromBundle("dataverse.update.featuredItems.error.typeAndDvObjectMismatch"));
}
if (dvObject instanceof DataFile) {
DataFile df = (DataFile)dvObject;
if (df.isRestricted()) {
throw new IllegalArgumentException(BundleUtil.getStringFromBundle("dataverseFeaturedItems.errors.restricted"));
}
if (!df.isReleased()) {
throw new IllegalArgumentException(BundleUtil.getStringFromBundle("dataverseFeaturedItems.errors.notPublished", List.of("Dataset")));
}
} else if (!dvObject.isReleased()) {
throw new IllegalArgumentException(BundleUtil.getStringFromBundle("dataverseFeaturedItems.errors.notPublished", List.of(CaseUtils.toCamelCase(dvType.name(), true))));
}
} else {
if (dvType != DataverseFeaturedItem.TYPES.CUSTOM) {
throw new IllegalArgumentException(BundleUtil.getStringFromBundle("find.dvo.error.dvObjectNotFound", List.of(dvIdtf == null ? "unknown" : dvIdtf)));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
package edu.harvard.iq.dataverse.dataverse.featured;

import com.google.common.collect.Lists;
import edu.harvard.iq.dataverse.*;
import edu.harvard.iq.dataverse.authorization.Permission;
import edu.harvard.iq.dataverse.authorization.users.User;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import edu.harvard.iq.dataverse.settings.JvmSettings;
import edu.harvard.iq.dataverse.util.BundleUtil;
import edu.harvard.iq.dataverse.util.FileUtil;
Expand All @@ -13,7 +9,6 @@
import jakarta.inject.Named;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.servlet.http.HttpServletRequest;

import java.io.File;
import java.io.IOException;
Expand All @@ -22,12 +17,14 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.EnumSet;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

@Stateless
@Named
public class DataverseFeaturedItemServiceBean implements Serializable {
private static final Logger logger = Logger.getLogger(DataverseFeaturedItemServiceBean.class.getCanonicalName());

public static class InvalidImageFileException extends Exception {
public InvalidImageFileException(String message) {
Expand Down Expand Up @@ -70,6 +67,25 @@ public void deleteAllByDvObjectId(Long id) {
.executeUpdate();
}

public void deleteInvalidatedFeaturedItemsByDataset(Dataset dataset) {
// Delete any Featured Items that contain Datafiles that were removed or restricted in the latest published version
List<DataverseFeaturedItem> featuredItems = findAllByDataverseOrdered(dataset.getOwner());
for (DataverseFeaturedItem featuredItem : featuredItems) {
if (featuredItem.getDvObject() != null && featuredItem.getType().equalsIgnoreCase(DataverseFeaturedItem.TYPES.DATAFILE.name())) {
DataFile df = (DataFile) featuredItem.getDvObject();
List<Long> latestVersionFileIds = new ArrayList<>();
dataset.getLatestVersion().getFileMetadatas().stream()
.map(FileMetadata::getId)
.forEachOrdered(latestVersionFileIds::add);
// If the datafile is restricted or part of this dataset but not in the latest version we need to delete the featured item
if (df.isRestricted() || (dataset.getFiles().contains(df) && !latestVersionFileIds.contains(df.getId()))) {
logger.fine("Deleting invalidated Featured Item for " + (df.isRestricted() ? "Restricted" : "Deleted") + "Datafile ID: " + df.getId());
deleteAllByDvObjectId(df.getId());
}
}
}
}

public List<DataverseFeaturedItem> findAllByDataverseOrdered(Dataverse dataverse) {
List<DataverseFeaturedItem> items = em
.createNamedQuery("DataverseFeaturedItem.findByDataverseOrderedByDisplayOrder", DataverseFeaturedItem.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -246,6 +246,9 @@ public Dataset execute(CommandContext ctxt) throws CommandException {

logger.info("Successfully published the dataset "+readyDataset.getGlobalId().asString());
readyDataset = ctxt.em().merge(readyDataset);

// Delete any Featured Items that are invalidated by publishing this version
ctxt.dataverseFeaturedItems().deleteInvalidatedFeaturedItemsByDataset(readyDataset);

return readyDataset;
}
Expand Down
26 changes: 23 additions & 3 deletions src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java
Original file line number Diff line number Diff line change
Expand Up @@ -1493,13 +1493,33 @@ public static JsonArrayBuilder jsonDataverseFeaturedItems(List<DataverseFeatured
}

public static JsonObjectBuilder json(DataverseFeaturedItem dataverseFeaturedItem) {
return jsonObjectBuilder()
NullSafeJsonBuilder job = jsonObjectBuilder()
.add("id", dataverseFeaturedItem.getId())
.add("content", dataverseFeaturedItem.getContent())
.add("imageFileName", dataverseFeaturedItem.getImageFileName())
.add("imageFileUrl", dataverseFeaturedItem.getImageFileUrl())
.add("displayOrder", dataverseFeaturedItem.getDisplayOrder())
.add("type", dataverseFeaturedItem.getType())
.add("dvObject", (dataverseFeaturedItem.getDvObject() != null) ? dataverseFeaturedItem.getDvObject().getId() : null);
.add("type", dataverseFeaturedItem.getType());

DvObject dvObject = dataverseFeaturedItem.getDvObject();
if (dvObject != null) {
String identifier = null;
String displayName = null;

if (dvObject.isInstanceofDataverse()) {
identifier = ((Dataverse) dvObject).getAlias();
displayName = ((Dataverse) dvObject).getName();
} else if (dvObject.isInstanceofDataset()) {
identifier = dvObject.getGlobalId() != null ? dvObject.getGlobalId().asString() : String.valueOf(dvObject.getId());
displayName = ((Dataset) dvObject).getCurrentName();
} else if (dvObject.isInstanceofDataFile()) {
identifier = String.valueOf(dvObject.getId());
displayName = ((DataFile) dvObject).getDisplayName();
}

job.add("dvObjectIdentifier", identifier);
job.add("dvObjectDisplayName", displayName);
}
return job;
}
}
2 changes: 2 additions & 0 deletions src/main/java/propertyFiles/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3195,6 +3195,8 @@ sendfeedback.fromEmail.error.invalid=Invalid fromEmail: {0}

#DataverseFeaturedItems.java
dataverseFeaturedItems.errors.notFound=Could not find dataverse featured item with identifier {0}
dataverseFeaturedItems.errors.notPublished={0} must be published to be featured.
dataverseFeaturedItems.errors.restricted=Datafile must not be restricted to be featured.
dataverseFeaturedItems.delete.successful=Successfully deleted dataverse featured item with identifier {0}

#DatasetFieldValidator.java
Expand Down
Loading