package edu.harvard.iq.dataverse.engine.command.impl;
import edu.harvard.iq.dataverse.Dataset;
import edu.harvard.iq.dataverse.DatasetVersion;
import edu.harvard.iq.dataverse.FileMetadata;
import edu.harvard.iq.dataverse.RoleAssignment;
import edu.harvard.iq.dataverse.authorization.Permission;
import edu.harvard.iq.dataverse.authorization.users.PrivateUrlUser;
import edu.harvard.iq.dataverse.engine.command.AbstractVoidCommand;
import edu.harvard.iq.dataverse.engine.command.CommandContext;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import edu.harvard.iq.dataverse.engine.command.RequiredPermissions;
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
import edu.harvard.iq.dataverse.engine.command.exception.IllegalCommandException;
import edu.harvard.iq.dataverse.privateurl.PrivateUrl;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;
/**
*
* @author skraffmiller
*/
@RequiredPermissions(Permission.DeleteDatasetDraft)
public class DeleteDatasetVersionCommand extends AbstractVoidCommand {
private static final Logger logger = Logger.getLogger(DeleteDatasetVersionCommand.class.getCanonicalName());
private final Dataset doomed;
public DeleteDatasetVersionCommand(DataverseRequest aRequest, Dataset dataset) {
super(aRequest, dataset);
this.doomed = dataset;
}
@Override
protected void executeImpl(CommandContext ctxt) throws CommandException {
// if you are deleting a dataset that only has 1 draft, we are actually destroying the dataset
if (doomed.getVersions().size() == 1) {
ctxt.engine().submit(new DestroyDatasetCommand(doomed, getRequest()));
} else {
// we are only deleting a version
// todo: for now, it's only the latest and if it's a draft
// but we should add the ability to destroy a specific version
DatasetVersion doomedVersion = doomed.getLatestVersion();
if (doomedVersion.isDraft()) {
Long versionId = doomedVersion.getId();
// files
Iterator<FileMetadata> fmIt = doomedVersion.getFileMetadatas().iterator();
while (fmIt.hasNext()) {
FileMetadata fmd = fmIt.next();
if (!fmd.getDataFile().isReleased()) {
// if file is draft (ie. new to this version, delete
// and remove fileMetadata from list (so that it won't try to merge)
ctxt.engine().submit(new DeleteDataFileCommand(fmd.getDataFile(), getRequest()));
fmIt.remove();
}
}
DatasetVersion doomedAndMerged = ctxt.em().merge(doomedVersion);
ctxt.em().remove(doomedAndMerged);
//remove version from ds obj before indexing....
Iterator<DatasetVersion> dvIt = doomed.getVersions().iterator();
while (dvIt.hasNext()) {
DatasetVersion dv = dvIt.next();
if (versionId.equals(dv.getId())) {
dvIt.remove();
}
}
/**
* DeleteDatasetDraft, which is required by this command,
* DeleteDatasetVersionCommand is not sufficient for running
* GetPrivateUrlCommand nor DeletePrivateUrlCommand, both of
* which require ManageDatasetPermissions because
* DeletePrivateUrlCommand calls RevokeRoleCommand which
* requires ManageDatasetPermissions when executed on a dataset
* so we make direct calls to the service bean so that a lowly
* Contributor who does NOT have ManageDatasetPermissions can
* still successfully delete a Private URL.
*/
PrivateUrl privateUrl = ctxt.privateUrl().getPrivateUrlFromDatasetId(doomed.getId());
if (privateUrl != null) {
logger.fine("Deleting Private URL for dataset id " + doomed.getId());
PrivateUrlUser privateUrlUser = new PrivateUrlUser(doomed.getId());
List<RoleAssignment> roleAssignments = ctxt.roles().directRoleAssignments(privateUrlUser, doomed);
for (RoleAssignment roleAssignment : roleAssignments) {
ctxt.roles().revoke(roleAssignment);
}
}
boolean doNormalSolrDocCleanUp = true;
ctxt.index().indexDataset(doomed, doNormalSolrDocCleanUp);
return;
}
throw new IllegalCommandException("Cannot delete a released version", this);
}
}
}