Skip to content

Commit

Permalink
Merge pull request #6893 from IQSS/6574-filenames
Browse files Browse the repository at this point in the history
6574 filenames
  • Loading branch information
kcondon committed May 7, 2020
2 parents e09e262 + e79280b commit 3c2e7e6
Show file tree
Hide file tree
Showing 6 changed files with 373 additions and 1 deletion.
2 changes: 1 addition & 1 deletion conf/docker-aio/run-test-suite.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ fi

# Please note the "dataverse.test.baseurl" is set to run for "all-in-one" Docker environment.
# TODO: Rather than hard-coding the list of "IT" classes here, add a profile to pom.xml.
mvn test -Dtest=DataversesIT,DatasetsIT,SwordIT,AdminIT,BuiltinUsersIT,UsersIT,UtilIT,ConfirmEmailIT,FileMetadataIT,FilesIT,SearchIT,InReviewWorkflowIT,HarvestingServerIT,MoveIT,MakeDataCountApiIT,FileTypeDetectionIT,EditDDIIT,ExternalToolsIT,AccessIT -Ddataverse.test.baseurl=$dvurl
mvn test -Dtest=DataversesIT,DatasetsIT,SwordIT,AdminIT,BuiltinUsersIT,UsersIT,UtilIT,ConfirmEmailIT,FileMetadataIT,FilesIT,SearchIT,InReviewWorkflowIT,HarvestingServerIT,MoveIT,MakeDataCountApiIT,FileTypeDetectionIT,EditDDIIT,ExternalToolsIT,AccessIT,DuplicateFilesIT -Ddataverse.test.baseurl=$dvurl
6 changes: 6 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/EditDatafilesPage.java
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
import org.apache.commons.httpclient.methods.GetMethod;
import java.text.DateFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Set;
import java.util.logging.Level;
import javax.faces.event.AjaxBehaviorEvent;
Expand Down Expand Up @@ -1092,6 +1093,11 @@ public String saveReplacementFile() throws FileReplaceException{
}

public String save() {
Collection<String> duplicates = IngestUtil.findDuplicateFilenames(workingVersion);
if (!duplicates.isEmpty()) {
JH.addMessage(FacesMessage.SEVERITY_ERROR, BundleUtil.getStringFromBundle("dataset.message.filesFailure"), BundleUtil.getStringFromBundle("dataset.message.editMetadata.duplicateFilenames", new ArrayList<>(duplicates)));
return null;
}
if (!saveEnabled) {
return "";
}
Expand Down
20 changes: 20 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/api/Files.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
import edu.harvard.iq.dataverse.export.ExportService;
import edu.harvard.iq.dataverse.ingest.IngestRequest;
import edu.harvard.iq.dataverse.ingest.IngestServiceBean;
import edu.harvard.iq.dataverse.ingest.IngestUtil;
import edu.harvard.iq.dataverse.makedatacount.MakeDataCountLoggingServiceBean;
import edu.harvard.iq.dataverse.settings.SettingsServiceBean;
import edu.harvard.iq.dataverse.util.BundleUtil;
Expand All @@ -41,13 +42,16 @@
import edu.harvard.iq.dataverse.util.SystemConfig;
import edu.harvard.iq.dataverse.util.json.NullSafeJsonBuilder;
import java.io.InputStream;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.inject.Inject;
import javax.json.Json;
import javax.json.JsonReader;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.Consumes;
import javax.ws.rs.DELETE;
Expand Down Expand Up @@ -384,6 +388,22 @@ public Response updateFileMetadata(@FormDataParam("jsonData") String jsonData,
return error(Response.Status.BAD_REQUEST, "An error has occurred attempting to update the requested DataFile. It is not part of the current version of the Dataset.");
}

JsonReader jsonReader = Json.createReader(new StringReader(jsonData));
javax.json.JsonObject jsonObject = jsonReader.readObject();
String label = jsonObject.getString("label", null);
String directoryLabel = jsonObject.getString("directoryLabel", null);
String path = "";
if (directoryLabel != null) {
path = directoryLabel + "/";
}
if (label == null) {
label = df.getFileMetadata().getLabel();
}
if (IngestUtil.conflictsWithExistingFilenames(label, directoryLabel, fmdList, df)) {
String incomingPathPlusFileName = path + label;
return error(BAD_REQUEST, BundleUtil.getStringFromBundle("files.api.metadata.update.duplicateFile", Arrays.asList(incomingPathPlusFileName)));
}

optionalFileParams.addOptionalParams(upFmd);

Dataset upDS = execCommand(new UpdateDatasetVersionCommand(upFmd.getDataFile().getOwner(), req));
Expand Down
76 changes: 76 additions & 0 deletions src/main/java/edu/harvard/iq/dataverse/ingest/IngestUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -100,6 +101,81 @@ public static String duplicateFilenameCheck(FileMetadata fileMetadata, Set<Strin
return fileName;
}

/**
* Given a new proposed label or directoryLabel for a file, check against
* existing files if a duplicate directoryLabel/label combination would be
* created.
*
* @param label The new label (filename) that is being proposed. Can be
* null.
* @param directoryLabel The new directoryLabel (file path) that is being
* proposed. Can be null.
* @param fileMetadatas The list fileMetadatas to be compared against,
* probably from a draft.
* @param dataFile The file that is being updated with a new name or path.
* @return true if there is a conflict, false otherwise.
*/
public static boolean conflictsWithExistingFilenames(String label, String directoryLabel, List<FileMetadata> fileMetadatas, DataFile dataFile) {
List<String> filePathsAndNames = getPathsAndFileNames(fileMetadatas);
if (label != null || directoryLabel != null) {
String path = "";
if (directoryLabel != null) {
path = directoryLabel + "/";
}
if (label == null) {
label = dataFile.getFileMetadata().getLabel();
}
String incomingPathPlusFileName = path + label;
logger.fine(filePathsAndNames.toString());
logger.fine("incomingPathName: " + incomingPathPlusFileName);
if (filePathsAndNames.contains(incomingPathPlusFileName)) {
return true;
}
}
return false;
}

/**
* Given a DatasetVersion, iterate across all the files (including their
* paths) and return any duplicates.
*
* @param datasetVersion
* @return A Collection of Strings in the form of path/to/file.txt
*/
public static Collection<String> findDuplicateFilenames(DatasetVersion datasetVersion) {
List<String> allFileNamesWithPaths = getPathsAndFileNames(datasetVersion.getFileMetadatas());
return findDuplicates(allFileNamesWithPaths);
}

// https://stackoverflow.com/questions/7414667/identify-duplicates-in-a-list
private static <T> Set<T> findDuplicates(Collection<T> collection) {
Set<T> duplicates = new HashSet<>();
Set<T> uniques = new HashSet<>();
for (T t : collection) {
if (!uniques.add(t)) {
duplicates.add(t);
}
}
return duplicates;
}

/**
* @return A List of Strings in the form of path/to/file.txt
*/
public static List<String> getPathsAndFileNames(List<FileMetadata> fileMetadatas) {
List<String> allFileNamesWithPaths = new ArrayList<>();
for (FileMetadata fileMetadata : fileMetadatas) {
String directoryLabel = fileMetadata.getDirectoryLabel();
String path = "";
if (directoryLabel != null) {
path = directoryLabel + "/";
}
String pathAndfileName = path + fileMetadata.getLabel();
allFileNamesWithPaths.add(pathAndfileName);
}
return allFileNamesWithPaths;
}

// This method is called on a single file, when we need to modify the name
// of an already ingested/persisted datafile. For ex., when we have converted
// a file to tabular data, and want to update the extension accordingly.
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/propertyFiles/Bundle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1358,6 +1358,7 @@ dataset.message.uploadFilesSingle.message=For more information about supported f
dataset.message.uploadFilesMultiple.message=Multiple file upload/download methods are available for this dataset. Once you upload a file using one of these methods, your choice will be locked in for this dataset.
dataset.message.editMetadata.label=Edit Dataset Metadata
dataset.message.editMetadata.message=Add more metadata about this dataset to help others easily find it.
dataset.message.editMetadata.duplicateFilenames=Duplicate filenames: {0}
dataset.message.editTerms.label=Edit Dataset Terms
dataset.message.editTerms.message=Add the terms of use for this dataset to explain how to access and use your data.
dataset.message.locked.editNotAllowedInReview=Dataset cannot be edited due to In Review dataset lock.
Expand Down Expand Up @@ -2238,6 +2239,9 @@ admin.api.deleteUser.failure.groupMember=the user is a member of Explicit Group(
admin.api.deleteUser.failure.pendingRequests=the user has pending File Access Request(s)
admin.api.deleteUser.success=Authenticated User {0} deleted.

#Files.java
files.api.metadata.update.duplicateFile=Filename already exists at {0}

#Datasets.java
datasets.api.updatePIDMetadata.failure.dataset.must.be.released=Modify Registration Metadata must be run on a published dataset.
datasets.api.updatePIDMetadata.auth.mustBeSuperUser=Forbidden. You must be a superuser.
Expand Down
Loading

0 comments on commit 3c2e7e6

Please sign in to comment.