From b8b8e3ce8ad5472ff00d7027703b4e206629d986 Mon Sep 17 00:00:00 2001 From: Leonid Andreev Date: Mon, 27 Apr 2020 22:17:56 -0400 Subject: [PATCH] make sure that we delete both the worldmap entities on the dataverse side, and possible remote layer data. #4093 --- .../edu/harvard/iq/dataverse/DataFile.java | 8 ++++++ .../command/impl/DeleteDataFileCommand.java | 28 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/main/java/edu/harvard/iq/dataverse/DataFile.java b/src/main/java/edu/harvard/iq/dataverse/DataFile.java index 8c5653d0199..6218629549c 100644 --- a/src/main/java/edu/harvard/iq/dataverse/DataFile.java +++ b/src/main/java/edu/harvard/iq/dataverse/DataFile.java @@ -19,6 +19,7 @@ import edu.harvard.iq.dataverse.util.FileUtil; import edu.harvard.iq.dataverse.util.ShapefileHandler; import edu.harvard.iq.dataverse.util.StringUtil; +import edu.harvard.iq.dataverse.worldmapauth.WorldMapToken; import java.io.IOException; import java.util.List; import java.util.ArrayList; @@ -214,6 +215,13 @@ public void setGuestbookResponses(List guestbookResponses) { this.guestbookResponses = guestbookResponses; } + // The WorldMap LayerMetadata and AuthToken are here to facilitate a + // clean cascade delete when the DataFile is deleted: + @OneToOne(mappedBy="dataFile", orphanRemoval = true, cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST}) + private MapLayerMetadata mapLayerMetadata; + @OneToMany(mappedBy="dataFile", orphanRemoval = true, cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST}) + private List worldMapTokens; + private char ingestStatus = INGEST_STATUS_NONE; @OneToOne(mappedBy = "thumbnailFile") diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java index deba1d7b6be..bc2ce4286f7 100644 --- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java +++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataFileCommand.java @@ -24,6 +24,9 @@ import java.util.logging.Level; import java.util.logging.Logger; import edu.harvard.iq.dataverse.GlobalIdServiceBean; +import edu.harvard.iq.dataverse.UserNotification; +import java.sql.Timestamp; +import java.util.Date; /** * Deletes a data file, both DB entity and filesystem object. @@ -210,6 +213,31 @@ public FileVisitResult postVisitDirectory(final Path dir, final IOException e) } catch (Exception e) { logger.log(Level.WARNING, "Identifier deletion was not successfull:", e.getMessage()); } + + // If there is a Map Layer associated with this file, we may need to + // try and remove the layer data on the WorldMap side. + if (ctxt.mapLayerMetadata().findMetadataByDatafile(doomed) != null) { + // (We need an AuthenticatedUser in order to produce a WorldMap token!) + String id = getUser().getIdentifier(); + id = id.startsWith("@") ? id.substring(1) : id; + AuthenticatedUser authenticatedUser = ctxt.authentication().getAuthenticatedUser(id); + try { + ctxt.mapLayerMetadata().deleteMapLayerFromWorldMap(doomed, authenticatedUser); + + // We have the dedicatd command DeleteMapLayerMetadataCommand, but + // there's no need to use it explicitly, since the Dataverse-side + // MapLayerMetadata entity will be deleted by the database + // cascade on the DataFile. -- L.A. Apr. 2020 + + } catch (Exception ex) { + // We are not going to treat it as a fatal condition and bail out, + // but we will send a notification to the user, warning them + // there may still be some data associated with the mapped layer, + // on the WorldMap side, un-deleted: + ctxt.notifications().sendNotification(authenticatedUser, new Timestamp(new Date().getTime()), UserNotification.Type.MAPLAYERDELETEFAILED, doomed.getFileMetadata().getId()); + } + + } DataFile doomedAndMerged = ctxt.em().merge(doomed); ctxt.em().remove(doomedAndMerged); /**