Skip to content

Commit d5e8cee

Browse files
Merge branch 'develop' into 11447-mydata-retrieve-empty-result-set
2 parents cc1d767 + ec1b65b commit d5e8cee

24 files changed

Lines changed: 284 additions & 47 deletions
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
## Bug: Publish and Submit for review must contain files
2+
When `requireFilesToPublishDataset` is set on a Dataverse a Dataset must contain files to be published or submitted for review. This fix make sure the dataset version contains files, and not just the dataset. It also adds this check to the `Submit for Review` functionality.
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
This release changes the display behavior of the file, dataset and collection ("dataverse") pages for tabular files. They will show the original file name and information, and will allow editing of the original file name. The ingested *.tab version is still available from the download menu.
2+

doc/sphinx-guides/source/api/changelog.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ v6.11
1212

1313
- The GET /api/mydata/retrieve, if the search returns no data, now includes the "data" block with 0 results. The message that was returned in "error_message" will be returned in "message" and the "success" will be `true`. All other errors will continue to reply with "success":false and the error message in "error_message".
1414

15+
- The following API will now return ``403`` if the ``requireFilesToPublishDataset`` flag is set and the dataset version contains 0 files.
16+
17+
- **/api/datasets/{Id}/submitForReview**
18+
1519
- The Croissant :ref:`metadata export format <metadata-export-formats>` has been updated from version 1.0 to 1.1, which is reflected in the ``conformsTo`` property. The unused ``wd`` property has been dropped.
1620

1721
v6.10

doc/sphinx-guides/source/api/native-api.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1299,7 +1299,7 @@ The following attributes are supported:
12991299
* ``description`` Description
13001300
* ``affiliation`` Affiliation
13011301
* ``filePIDsEnabled`` ("true" or "false") Restricted to use by superusers and only when the :ref:`:AllowEnablingFilePIDsPerCollection <:AllowEnablingFilePIDsPerCollection>` setting is true. Enables or disables registration of file-level PIDs in datasets within the collection (overriding the instance-wide setting).
1302-
* ``requireFilesToPublishDataset`` ("true" or "false") Restricted to use by superusers. Defines if Dataset needs files in order to be published. If not set the determination will be made through inheritance by checking the owners of this collection. Publishing by a superusers will not be blocked.
1302+
* ``requireFilesToPublishDataset`` ("true" or "false") Restricted to use by superusers. Defines if Dataset version needs files in order to be published or submitted for review. If not set the determination will be made through inheritance by checking the owners of this collection. Publishing by a superusers will not be blocked.
13031303
* ``allowedDatasetTypes`` Restricted to use by superusers. By default "dataset" is implied. Pass a comma-separated list of dataset types (e.g. "dataset,software"). You cannot unset this attribute so if you want to delete a dataset type, set ``allowedDatasetTypes`` to a dataset type you won't be deleting. See also :ref:`dataset-types`.
13041304

13051305
See also :ref:`update-dataverse-api`.

src/main/java/edu/harvard/iq/dataverse/DataCitation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ public DataCitation(FileMetadata fm, boolean direct) {
141141
getCommonValuesFrom(dsv);
142142

143143
// file Title for direct File citation
144-
fileTitle = fm.getLabel();
144+
fileTitle = fm.getLabelForOriginal();
145145
DataFile df = fm.getDataFile();
146146

147147
// File description

src/main/java/edu/harvard/iq/dataverse/DataFile.java

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,11 @@ public Long getOriginalFileSize() {
547547
return null;
548548
}
549549

550+
public String getFriendlyOriginalFileSize() {
551+
Long size = (getOriginalFileSize()==null) ? filesize : getOriginalFileSize();
552+
return getFriendlySize(size);
553+
}
554+
550555
public String getOriginalFileName() {
551556
if (isTabularData()) {
552557
DataTable dataTable = getDataTable();
@@ -559,7 +564,7 @@ public String getOriginalFileName() {
559564
}
560565

561566

562-
private String getDerivedOriginalFileName() {
567+
public String getDerivedOriginalFileName() {
563568
FileMetadata fm = getFileMetadata();
564569
String filename = fm.getLabel();
565570
String originalExtension = FileUtil.generateOriginalExtension(getOriginalFileFormat());
@@ -709,8 +714,12 @@ public void setFilesize(long filesize) {
709714
* @return
710715
*/
711716
public String getFriendlySize() {
712-
if (filesize != null) {
713-
return FileSizeChecker.bytesToHumanReadable(filesize);
717+
return getFriendlySize(filesize);
718+
}
719+
720+
private String getFriendlySize(Long size) {
721+
if (size != null) {
722+
return FileSizeChecker.bytesToHumanReadable(size);
714723
} else {
715724
return BundleUtil.getStringFromBundle("file.sizeNotAvailable");
716725
}

src/main/java/edu/harvard/iq/dataverse/DatasetServiceBean.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,6 +835,18 @@ public String getReminderString(Dataset dataset, boolean canPublishDataset, bool
835835

836836
String reminderString;
837837

838+
if (dataset.getOwner().getEffectiveRequiresFilesToPublishDataset()) {
839+
List<FileMetadata> files = dataset.getLatestVersion().getFileMetadatas();
840+
if (files.size() < 1) {
841+
if (canPublishDataset) {
842+
reminderString = BundleUtil.getStringFromBundle("dataset.mayNotPublish.FilesRequired");
843+
} else {
844+
reminderString = BundleUtil.getStringFromBundle("dataset.mayNotSubmitForReview.FilesRequired");
845+
}
846+
return reminderString;
847+
}
848+
}
849+
838850
if (canPublishDataset) {
839851
reminderString = BundleUtil.getStringFromBundle("dataset.message.publish.warning");
840852
} else {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package edu.harvard.iq.dataverse;
2+
3+
import jakarta.validation.ConstraintValidator;
4+
import jakarta.validation.ConstraintValidatorContext;
5+
6+
import java.util.regex.Matcher;
7+
import java.util.regex.Pattern;
8+
9+
public class FileLabelValidator implements ConstraintValidator<ValidateDataFileLabel, String> {
10+
11+
@Override
12+
public void initialize(ValidateDataFileLabel constraintAnnotation) {
13+
14+
}
15+
16+
@Override
17+
public boolean isValid(String value, ConstraintValidatorContext context) {
18+
return isFileLabelValid(value, context);
19+
20+
}
21+
22+
public static boolean isFileLabelValid(String value, ConstraintValidatorContext context) {
23+
24+
if (value == null || value.isEmpty()) {
25+
return true;
26+
}
27+
String validCharacters = "^[^:<>;#/\"\\*\\|\\?\\\\]*$";
28+
Pattern p = Pattern.compile(validCharacters);
29+
Matcher m = p.matcher(value);
30+
return m.matches();
31+
32+
}
33+
34+
}

src/main/java/edu/harvard/iq/dataverse/FileMetadata.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import jakarta.persistence.NamedNativeQuery;
4040
import jakarta.persistence.OneToMany;
4141
import jakarta.persistence.OrderBy;
42+
import jakarta.persistence.PostLoad;
4243
import jakarta.persistence.SqlResultSetMapping;
4344
import jakarta.persistence.Table;
4445
import jakarta.persistence.Transient;
@@ -153,6 +154,18 @@ public class FileMetadata implements Serializable {
153154
@OneToMany (mappedBy="fileMetadata", cascade={ CascadeType.REMOVE, CascadeType.MERGE,CascadeType.PERSIST})
154155
private Collection<VariableMetadata> variableMetadatas;
155156

157+
// A transient field is needed for JSF UI - validation errors on label do not get routed directly to the input for labelNoExtension, causing rollback.
158+
// With a separate transient field kept in sync with label, the validation can be done on the labelNoExtension field, which avoids the issue and allows proper validation.
159+
@Transient
160+
@ValidateDataFileLabel(message = "{filename.illegalCharacters}")
161+
String labelNoExtension;
162+
163+
// Initialize the labelNoExtension from label after loading the entity
164+
@PostLoad
165+
public void postLoad() {
166+
getLabelNoExtension();
167+
}
168+
156169
/**
157170
* Creates a copy of {@code this}, with identical business logic fields, making the bi-drectional connections to the specified version.
158171
*
@@ -173,13 +186,46 @@ public FileMetadata createCopyInVersion(DatasetVersion dsv) {
173186
}
174187

175188
public String getLabel() {
189+
getLabelNoExtension();
176190
return label;
177191
}
178192

179193
public void setLabel(String label) {
180194
this.label = label;
195+
getLabelNoExtension();
196+
}
197+
198+
199+
public String getLabelNoExtension() {
200+
int last = label.lastIndexOf(".");
201+
labelNoExtension = (last == -1) ? label : label.substring(0, last);
202+
return labelNoExtension;
203+
}
204+
205+
public String getOriginalExtension() {
206+
String origFilename = getLabelForOriginal();
207+
int last = origFilename.lastIndexOf(".");
208+
return (last == -1) ? "" : origFilename.substring(last);
181209
}
182210

211+
public void setLabelNoExtension(String name) {
212+
labelNoExtension = name;
213+
int last = this.label.lastIndexOf(".");
214+
if (last == -1) {
215+
this.label = name;
216+
} else {
217+
this.label = name + this.label.substring(last);
218+
}
219+
}
220+
221+
public String getLabelForOriginal() {
222+
if(dataFile.isTabularData()) {
223+
return dataFile.getDerivedOriginalFileName();
224+
} else {
225+
return label;
226+
}
227+
}
228+
183229
public FileMetadata() {
184230
variableMetadatas = new ArrayList<VariableMetadata>();
185231
varGroups = new ArrayList<VarGroup>();

src/main/java/edu/harvard/iq/dataverse/PermissionsWrapper.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
1313
import edu.harvard.iq.dataverse.engine.command.impl.*;
1414
import java.util.HashMap;
15+
import java.util.List;
1516
import java.util.Map;
1617
import java.util.logging.Logger;
1718
import jakarta.ejb.EJB;
@@ -253,9 +254,38 @@ public boolean canIssueDeleteDatasetCommand(DvObject dvo){
253254

254255
// PUBLISH DATASET
255256
public boolean canIssuePublishDatasetCommand(DvObject dvo){
257+
User u = session.getUser();
258+
if (u != null && u.isSuperuser()) {
259+
return true;
260+
}
261+
// Return false if dataset has 0 files and user want to 'publish' or 'submit for review' and 'publish dataset requires files' flag is set
262+
if (dvo.isInstanceofDataset()) {
263+
Dataverse dv =((Dataset)dvo).getOwner();
264+
if (dv != null) {
265+
List<FileMetadata> metadataList = ((Dataset) dvo).getLatestVersion().getFileMetadatas();
266+
if (metadataList.size() == 0 && dv.getEffectiveRequiresFilesToPublishDataset()) {
267+
return false;
268+
}
269+
}
270+
}
256271
return canIssueCommand(dvo, PublishDatasetCommand.class);
257272
}
258-
273+
274+
// SUBMIT DATASET FOR REVIEW
275+
public boolean canIssueSubmitDatasetForReviewCommand(DvObject dvo){
276+
// Return false if dataset has 0 files and user want to 'publish' or 'submit for review' and 'publish dataset requires files' flag is set
277+
if (dvo.isInstanceofDataset()) {
278+
Dataverse dv =((Dataset)dvo).getOwner();
279+
if (dv != null) {
280+
List<FileMetadata> metadataList = ((Dataset) dvo).getLatestVersion().getFileMetadatas();
281+
if (metadataList.size() == 0 && dv.getEffectiveRequiresFilesToPublishDataset()) {
282+
return false;
283+
}
284+
}
285+
}
286+
return canIssueCommand(dvo, SubmitDatasetForReviewCommand.class);
287+
}
288+
259289
// For the dataverse_header fragment (and therefore, most of the pages),
260290
// we need to know if authenticated users can add dataverses and datasets to the
261291
// root collection. For the "Add Data" menu further in the search include fragment

0 commit comments

Comments
 (0)