• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

IQSS / dataverse / #22002

01 Apr 2024 07:56PM CUT coverage: 20.716% (+0.5%) from 20.173%
#22002

push

github

web-flow
Merge pull request #10453 from IQSS/develop

Merge 6.2 into master

704 of 2679 new or added lines in 152 files covered. (26.28%)

81 existing lines in 49 files now uncovered.

17160 of 82836 relevant lines covered (20.72%)

0.21 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

32.66
/src/main/java/edu/harvard/iq/dataverse/DataFile.java
1
package edu.harvard.iq.dataverse;
2

3
import com.google.gson.Gson;
4
import com.google.gson.GsonBuilder;
5
import com.google.gson.JsonElement;
6
import com.google.gson.JsonObject;
7
import com.google.gson.annotations.Expose;
8
import edu.harvard.iq.dataverse.DatasetVersion.VersionState;
9
import edu.harvard.iq.dataverse.authorization.RoleAssignee;
10
import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
11
import edu.harvard.iq.dataverse.dataaccess.DataAccess;
12
import edu.harvard.iq.dataverse.dataaccess.StorageIO;
13
import edu.harvard.iq.dataverse.datasetutility.FileSizeChecker;
14
import edu.harvard.iq.dataverse.ingest.IngestReport;
15
import edu.harvard.iq.dataverse.ingest.IngestRequest;
16
import edu.harvard.iq.dataverse.util.BundleUtil;
17
import edu.harvard.iq.dataverse.util.FileUtil;
18
import edu.harvard.iq.dataverse.util.ShapefileHandler;
19
import edu.harvard.iq.dataverse.util.StringUtil;
20
import java.io.IOException;
21
import java.util.List;
22
import java.util.ArrayList;
23
import java.util.Objects;
24
import java.text.SimpleDateFormat;
25
import java.util.Arrays;
26
import java.util.HashMap;
27
import java.util.Map;
28
import java.util.Set;
29
import java.util.logging.Logger;
30
import java.util.stream.Collectors;
31
import jakarta.json.Json;
32
import jakarta.json.JsonArrayBuilder;
33
import jakarta.persistence.*;
34
import jakarta.validation.constraints.Pattern;
35
import jakarta.validation.constraints.NotBlank;
36

37
/**
38
 *
39
 * @author gdurand
40
 */
41
@NamedQueries({
42
        @NamedQuery( name="DataFile.removeFromDatasetVersion",
43
                query="DELETE FROM FileMetadata f WHERE f.datasetVersion.id=:versionId and f.dataFile.id=:fileId"),
44
        @NamedQuery(name = "DataFile.findByCreatorId",
45
                query = "SELECT o FROM DataFile o WHERE o.creator.id=:creatorId"),
46
        @NamedQuery(name = "DataFile.findByReleaseUserId",
47
                query = "SELECT o FROM DataFile o WHERE o.releaseUser.id=:releaseUserId"),
48
        @NamedQuery(name="DataFile.findDataFileByIdProtocolAuth",
49
                query="SELECT s FROM DataFile s WHERE s.identifier=:identifier AND s.protocol=:protocol AND s.authority=:authority"),
50
        @NamedQuery(name="DataFile.findDataFileThatReplacedId",
51
                query="SELECT s.id FROM DataFile s WHERE s.previousDataFileId=:identifier")
52
})
53
@Entity
54
@Table(indexes = {@Index(columnList="ingeststatus")
55
        , @Index(columnList="checksumvalue")
56
        , @Index(columnList="contenttype")
57
        , @Index(columnList="restricted")})
58
public class DataFile extends DvObject implements Comparable {
59
    private static final Logger logger = Logger.getLogger(DatasetPage.class.getCanonicalName());
1✔
60
    private static final long serialVersionUID = 1L;
61
    public static final String TARGET_URL = "/file.xhtml?persistentId=";
62
    public static final char INGEST_STATUS_NONE = 65;
63
    public static final char INGEST_STATUS_SCHEDULED = 66;
64
    public static final char INGEST_STATUS_INPROGRESS = 67;
65
    public static final char INGEST_STATUS_ERROR = 68; 
66
    
67
    public static final Long ROOT_DATAFILE_ID_DEFAULT = (long) -1;
1✔
68
    
69
    @Expose
70
    @NotBlank
71
    @Column( nullable = false )
72
    @Pattern(regexp = "^.*/.*$", message = "{contenttype.slash}")
73
    private String contentType;
74

75
//    @Expose    
76
//    @SerializedName("storageIdentifier")
77
//    @Column( nullable = false )
78
//    private String fileSystemName;
79

80
    /**
81
     * End users will see "SHA-1" (with a hyphen) rather than "SHA1" in the GUI
82
     * and API but in the "datafile" table we persist "SHA1" (no hyphen) for
83
     * type safety (using keys of the enum). In the "setting" table, we persist
84
     * "SHA-1" (with a hyphen) to match the GUI and the "Algorithm Name" list at
85
     * https://docs.oracle.com/javase/8/docs/technotes/guides/security/StandardNames.html#MessageDigest
86
     *
87
     * The list of types should be limited to the list above in the technote
88
     * because the string gets passed into MessageDigest.getInstance() and you
89
     * can't just pass in any old string.
90
     */
91
    public enum ChecksumType {
1✔
92

93
        MD5("MD5"),
1✔
94
        SHA1("SHA-1"),
1✔
95
        SHA256("SHA-256"),
1✔
96
        SHA512("SHA-512");
1✔
97

98
        private final String text;
99

100
        private ChecksumType(final String text) {
1✔
101
            this.text = text;
1✔
102
        }
1✔
103

104
        public static ChecksumType fromString(String text) {
105
            if (text != null) {
×
106
                for (ChecksumType checksumType : ChecksumType.values()) {
×
107
                    if (text.equals(checksumType.text)) {
×
108
                        return checksumType;
×
109
                    }
110
                }
111
            }
112
            throw new IllegalArgumentException("ChecksumType must be one of these values: " + Arrays.asList(ChecksumType.values()) + ".");
×
113
        }
114

115
        @Override
116
        public String toString() {
117
            return text;
×
118
        }
119
    }
120

121
    //@Expose
122
    @Column(nullable = false)
123
    @Enumerated(EnumType.STRING)
124
    private ChecksumType checksumType;
125

126
    /**
127
     * Examples include "f622da34d54bdc8ee541d6916ac1c16f" as an MD5 value or
128
     * "3a484dfdb1b429c2e15eb2a735f1f5e4d5b04ec6" as a SHA-1 value"
129
     */
130
    //@Expose
131
    @Column(nullable = false)
132
    private String checksumValue;
133

134
    
135
    /* start: FILE REPLACE ATTRIBUTES */
136
    
137
    // For the initial version of a file, this will be equivalent to the ID
138
    // Default is -1 until the intial id is generated
139
    @Expose
140
    @Column(nullable=false)
141
    private Long rootDataFileId;
142

143
    /**
144
     * @todo We should have consistency between "Id" vs "ID" for rootDataFileId
145
     * vs. previousDataFileId.
146
     */
147
    // null for initial version; subsequent versions will point to the previous file
148
    //
149
    @Expose
150
    @Column(nullable=true)
151
    private Long previousDataFileId;
152
    /* endt: FILE REPLACE ATTRIBUTES */
153
    
154
    
155
    
156
    @Expose
157
    @Column(nullable=true)
158
    private Long filesize;      // Number of bytes in file.  Allows 0 and null, negative numbers not permitted
159

160
    @Expose
161
    private boolean restricted;
162
    
163
    @Expose
164
    @Column(columnDefinition = "TEXT", nullable = true, name="prov_entityname")
165
    private String provEntityName;
166
    
167
    /*Add when we integrate with provCPL*/
168
    //The id given for the datafile by CPL.
169
//    @Column(name="prov_cplid") //( nullable=false )
170
//    private int provCplId;
171
    
172
    /*
173
        Tabular (formerly "subsettable") data files have DataTable objects
174
        associated with them:
175
    */
176
    
177
    @OneToMany(mappedBy = "dataFile", cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
178
    private List<DataTable> dataTables;
179
    
180
    @OneToMany(mappedBy = "dataFile", cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
181
    private List<AuxiliaryFile> auxiliaryFiles;
182
   
183
    @OneToMany(mappedBy = "dataFile", cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
184
    private List<IngestReport> ingestReports;
185
    
186
    @OneToOne(mappedBy = "dataFile", cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
187
    private IngestRequest ingestRequest;
188
    
189
    @OneToMany(mappedBy = "dataFile", orphanRemoval = true, cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
190
    private List<DataFileTag> dataFileTags;
191
    
192
    @OneToMany(mappedBy="dataFile", cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
193
    private List<FileMetadata> fileMetadatas;
194
    
195
    @OneToMany(mappedBy="dataFile", cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
196
    private List<GuestbookResponse> guestbookResponses;
197

198
    @OneToMany(mappedBy="dataFile",fetch = FetchType.LAZY,cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REFRESH})
199
    private List<FileAccessRequest> fileAccessRequests;
200

201
    @ManyToMany
202
    @JoinTable(name = "fileaccessrequests",
203
    joinColumns = @JoinColumn(name = "datafile_id"),
204
    inverseJoinColumns = @JoinColumn(name = "authenticated_user_id"))
205
    private List<AuthenticatedUser> fileAccessRequesters;
206

207
    
208
    public List<FileAccessRequest> getFileAccessRequests(){
209
        return fileAccessRequests;
×
210
    }
211
    
212
    public List<FileAccessRequest> getFileAccessRequests(FileAccessRequest.RequestState state){
213
        return fileAccessRequests.stream().filter(far -> far.getState() == state).collect(Collectors.toList());
×
214
    }
215

216
    public void setFileAccessRequests(List<FileAccessRequest> fARs){
217
        this.fileAccessRequests = fARs;
×
218
    }
×
219
    
220
    public List<GuestbookResponse> getGuestbookResponses() {
221
        return guestbookResponses;
×
222
    }
223

224
    public void setGuestbookResponses(List<GuestbookResponse> guestbookResponses) {
225
        this.guestbookResponses = guestbookResponses;
×
226
    }
×
227

228
    private char ingestStatus = INGEST_STATUS_NONE; 
1✔
229
    
230
    @OneToOne(mappedBy = "thumbnailFile")
231
    private Dataset thumbnailForDataset;
232

233
    @ManyToOne
234
    @JoinColumn(name="embargo_id")
235
    private Embargo embargo;
236

237
    public Embargo getEmbargo() {
238
        return embargo;
1✔
239
    }
240

241
    public void setEmbargo(Embargo embargo) {
242
        this.embargo = embargo;
1✔
243
    }
1✔
244

245
    public DataFile() {
1✔
246
        this.fileMetadatas = new ArrayList<>();
1✔
247
        initFileReplaceAttributes();
1✔
248
    }    
1✔
249

250
    public DataFile(String contentType) {
1✔
251
        this.contentType = contentType;
1✔
252
        this.fileMetadatas = new ArrayList<>();
1✔
253
        initFileReplaceAttributes();
1✔
254
    }
1✔
255

256
    /*
257
    Used in manage file permissions UI 
258
    to easily display those files that have been deleted in the current draft 
259
    or previous version which may have roles assigned or pending requests for access
260
    */
261
   
262
    @Transient
263
    private Boolean deleted;
264

265
    public Boolean getDeleted() {
266
        return deleted;
×
267
    }
268

269
    public void setDeleted(Boolean deleted) {
270
        this.deleted = deleted;
×
271
    }
×
272
    
273
    /*
274
    For use during file upload so that the user may delete 
275
    files that have already been uploaded to the current dataset version
276
    */
277
    
278
    @Transient
279
    private boolean markedAsDuplicate;
280

281
    public boolean isMarkedAsDuplicate() {
282
        return markedAsDuplicate;
×
283
    }
284

285
    public void setMarkedAsDuplicate(boolean markedAsDuplicate) {
286
        this.markedAsDuplicate = markedAsDuplicate;
×
287
    }
×
288
    
289
    @Transient
290
    private String duplicateFilename;
291

292
    public String getDuplicateFilename() {
293
        return duplicateFilename;
×
294
    }
295

296
    public void setDuplicateFilename(String duplicateFilename) {
297
        this.duplicateFilename = duplicateFilename;
×
298
    }
×
299

300
    public List<AuxiliaryFile> getAuxiliaryFiles() {
301
        return auxiliaryFiles;
×
302
    }
303

304
    public void setAuxiliaryFiles(List<AuxiliaryFile> auxiliaryFiles) {
305
        this.auxiliaryFiles = auxiliaryFiles;
×
306
    }
×
307
    
308
    
309
    
310
    
311
       
312
    /**
313
     * All constructors should use this method
314
     * to initialize this file replace attributes
315
     */
316
    private void initFileReplaceAttributes(){
317
        this.rootDataFileId = ROOT_DATAFILE_ID_DEFAULT;
1✔
318
        this.previousDataFileId = null;
1✔
319
    }
1✔
320
    
321
    @Override
322
    public boolean isEffectivelyPermissionRoot() {
323
        return false;
×
324
    }
325
    
326
    public List<DataTable> getDataTables() {
327
        return dataTables;
1✔
328
    }
329

330
    public void setDataTables(List<DataTable> dataTables) {
331
        this.dataTables = dataTables;
1✔
332
    }
1✔
333
    
334
    public DataTable getDataTable() {
335
        if ( getDataTables() != null && getDataTables().size() > 0 ) {
1✔
336
            return getDataTables().get(0);
1✔
337
        } else {
338
            return null;
×
339
        }
340
    }
341

342
    public void setDataTable(DataTable dt) {
343
        if (this.getDataTables() == null) {
1✔
344
            this.setDataTables(new ArrayList<>());
1✔
345
        } else {
346
            this.getDataTables().clear();
×
347
        }
348

349
        this.getDataTables().add(dt);
1✔
350
    }
1✔
351
    
352
    public List<DataFileTag> getTags() {
353
        return dataFileTags;
1✔
354
    }
355
    
356
    public List<String> getTagLabels(){
357
        
358
        List<DataFileTag> currentDataTags = this.getTags();
1✔
359
        List<String> tagStrings = new ArrayList<>();
1✔
360
        
361
        if (( currentDataTags != null)&&(!currentDataTags.isEmpty())){
1✔
362
                       
363
            for (DataFileTag element : currentDataTags) {
1✔
364
                tagStrings.add(element.getTypeLabel());
1✔
365
            }
1✔
366
        }
367
        return tagStrings;
1✔
368
    }
369

370
    public JsonArrayBuilder getTagLabelsAsJsonArrayBuilder(){
371
        
372
        List<DataFileTag> currentDataTags = this.getTags();
×
373

374
        JsonArrayBuilder builder = Json.createArrayBuilder();
×
375
        
376
        if ( (currentDataTags == null)||(currentDataTags.isEmpty())){
×
377
            return builder;
×
378
        }
379
        
380
        
381
        for (DataFileTag element : currentDataTags) {
×
382
            builder.add(element.getTypeLabel());            
×
383
        }
×
384
        return builder;
×
385
    }
386
    public void setTags(List<DataFileTag> dataFileTags) {
387
        this.dataFileTags = dataFileTags;
1✔
388
    }
1✔
389

390
    public void addUniqueTagByLabel(String tagLabel) throws IllegalArgumentException {
391
        if (tagExists(tagLabel)) {
×
392
            return;
×
393
        }
394
        DataFileTag tag = new DataFileTag();
×
395
        tag.setTypeByLabel(tagLabel);
×
396
        tag.setDataFile(this);
×
397
        addTag(tag);
×
398
    }
×
399

400
    public void addTag(DataFileTag tag) {
401
        if (dataFileTags == null) {
1✔
402
            dataFileTags = new ArrayList<>();
1✔
403
        } 
404

405
        dataFileTags.add(tag);
1✔
406
    }
1✔
407
    
408
    public List<FileMetadata> getFileMetadatas() {
409
        return fileMetadatas;
1✔
410
    }
411

412
    public void setFileMetadatas(List<FileMetadata> fileMetadatas) {
413
        this.fileMetadatas = fileMetadatas;
1✔
414
    }
1✔
415
    
416
    public IngestReport getIngestReport() {
417
        if ( ingestReports != null && ingestReports.size() > 0 ) {
×
418
            return ingestReports.get(0);
×
419
        } else {
420
            return null;
×
421
        }
422
    }
423

424
    public void setIngestReport(IngestReport report) {
425
        if (ingestReports == null) {
×
426
            ingestReports = new ArrayList<>();
×
427
        } else {
428
            ingestReports.clear();
×
429
        }
430

431
        ingestReports.add(report);
×
432
    }
×
433
    
434
    public IngestRequest getIngestRequest() {
435
        return ingestRequest;
×
436
    }
437
    
438
    public void setIngestRequest(IngestRequest ingestRequest) {
439
        this.ingestRequest = ingestRequest;
×
440
    }
×
441
    
442
    public String getIngestReportMessage() {
443
        if ( ingestReports != null && ingestReports.size() > 0 ) {
×
444
            if (ingestReports.get(0).getReport() != null && !"".equals(ingestReports.get(0).getReport())) {
×
445
                return ingestReports.get(0).getReport();
×
446
            }
447
        }
448
        return BundleUtil.getStringFromBundle("file.ingestFailed");
×
449
    }
450
    
451
    public boolean isTabularData() {
452
        return getDataTables() != null && getDataTables().size() > 0; 
1✔
453
    }
454
    
455
    public String getOriginalFileFormat() {
456
        if (isTabularData()) {
1✔
457
            DataTable dataTable = getDataTable();
1✔
458
            if (dataTable != null) {
1✔
459
                return dataTable.getOriginalFileFormat();
1✔
460
            }
461
        }
462
        return null;
×
463
    }
464
    
465
    public Long getOriginalFileSize() {
466
        if (isTabularData()) {
1✔
467
            DataTable dataTable = getDataTable();
1✔
468
            if (dataTable != null) {
1✔
469
                return dataTable.getOriginalFileSize();
1✔
470
            }
471
        }
472
        return null;
×
473
    }
474
    
475
    public String getOriginalFileName() {
476
        if (isTabularData()) {
1✔
477
            DataTable dataTable = getDataTable();
1✔
478
            if (dataTable != null) {
1✔
479
                return dataTable.getOriginalFileName() != null ? dataTable.getOriginalFileName()
1✔
480
                        : getDerivedOriginalFileName();
×
481
            }
482
        }
483
        return null;
×
484
    }
485

486
    
487
    private String getDerivedOriginalFileName() {
488
        FileMetadata fm = getFileMetadata();
×
489
        String filename = fm.getLabel();
×
490
        String originalExtension = FileUtil.generateOriginalExtension(getOriginalFileFormat());
×
491
        String extensionToRemove = StringUtil.substringIncludingLast(filename, ".");
×
492
        if (StringUtil.nonEmpty(extensionToRemove)) {
×
493
            return filename.replaceAll(extensionToRemove + "$", originalExtension);
×
494
        } else{
495
            return filename + originalExtension ;
×
496
        }        
497
    }
498

499
    @Override
500
    public boolean isAncestorOf( DvObject other ) {
501
        return equals(other);
×
502
    }
503
    
504
    /*
505
     * A user-friendly version of the "original format":
506
     */
507
    public String getOriginalFormatLabel() {
508
        return FileUtil.getUserFriendlyOriginalType(this);
1✔
509
    }
510

511
    public String getContentType() {
512
        return contentType;
1✔
513
    }
514

515
    public void setContentType(String contentType) {
516
        this.contentType = contentType;
1✔
517
    }
1✔
518

519
    public String getFriendlyType() {
520
        return FileUtil.getUserFriendlyFileType(this);
1✔
521
    }
522
    
523
    @Override
524
    public Dataset getOwner() {
525
        return (Dataset) super.getOwner();
1✔
526
    }
527

528
    public void setOwner(Dataset dataset) {
529
        super.setOwner(dataset);
1✔
530
    }
1✔
531
    
532
    public String getDescription() {
533
        FileMetadata fmd = getLatestFileMetadata();
×
534
        
535
        if (fmd == null) {
×
536
            return null;
×
537
        }
538
        return fmd.getDescription();
×
539
    }
540

541
    public void setDescription(String description) {
542
        FileMetadata fmd = getLatestFileMetadata();
×
543
        
544
        if (fmd != null) {
×
545
            fmd.setDescription(description);
×
546
        }
547
    }
×
548

549
    public FileMetadata getDraftFileMetadata() {
NEW
550
        FileMetadata latestFileMetadata = getLatestFileMetadata();
×
NEW
551
        if (latestFileMetadata.getDatasetVersion().isDraft()) {
×
NEW
552
            return latestFileMetadata;
×
553
        }
NEW
554
        return null;
×
555
    }
556
    
557
    public FileMetadata getFileMetadata() {
558
        return getLatestFileMetadata();
1✔
559
    }
560

561
    public FileMetadata getLatestFileMetadata() {
562
        FileMetadata resultFileMetadata = null;
1✔
563

564
        if (fileMetadatas.size() == 1) {
1✔
565
            return fileMetadatas.get(0);
1✔
566
        }
567

568
        for (FileMetadata fileMetadata : fileMetadatas) {
×
UNCOV
569
            if (fileMetadata.getDatasetVersion().getVersionState().equals(VersionState.DRAFT)) {
×
570
                return fileMetadata;
×
571
            }
NEW
572
            resultFileMetadata = getTheNewerFileMetadata(resultFileMetadata, fileMetadata);
×
573
        }
×
574

NEW
575
        return resultFileMetadata;
×
576
    }
577

578
    public FileMetadata getLatestPublishedFileMetadata() throws UnsupportedOperationException {
NEW
579
        FileMetadata resultFileMetadata = fileMetadatas.stream()
×
NEW
580
                .filter(metadata -> !metadata.getDatasetVersion().getVersionState().equals(VersionState.DRAFT))
×
NEW
581
                .reduce(null, DataFile::getTheNewerFileMetadata);
×
582

NEW
583
        if (resultFileMetadata == null) {
×
UNCOV
584
            throw new UnsupportedOperationException("No published metadata version for DataFile " + this.getId());
×
585
        }
586

NEW
587
        return resultFileMetadata;
×
588
    }
589

590
    public static FileMetadata getTheNewerFileMetadata(FileMetadata current, FileMetadata candidate) {
NEW
591
        if (current == null) {
×
NEW
592
            return candidate;
×
593
        }
594

NEW
595
        DatasetVersion currentVersion = current.getDatasetVersion();
×
NEW
596
        DatasetVersion candidateVersion = candidate.getDatasetVersion();
×
597

NEW
598
        if (DatasetVersion.compareByVersion.compare(candidateVersion, currentVersion) > 0) {
×
NEW
599
            return candidate;
×
600
        }
601

NEW
602
        return current;
×
603
    }
604

605
    /**
606
     * Get property filesize, number of bytes
607
     * @return value of property filesize.
608
     */
609
    public long getFilesize() {
610
        if (this.filesize == null) {
1✔
611
            // -1 means "unknown"
612
            return -1;
1✔
613
        }
614
        return this.filesize;
1✔
615
    }
616

617
    /**
618
     * Set property filesize in bytes
619
     * 
620
     * Allow nulls, but not negative numbers.
621
     * 
622
     * @param filesize new value of property filesize.
623
     */
624
    public void setFilesize(long filesize) {
625
        if (filesize < 0){
1✔
626
            return;
×
627
        }
628
       this.filesize = filesize;
1✔
629
    }
1✔
630

631
    /**
632
     * Converts the stored size of the file in bytes to 
633
     * a user-friendly value in KB, MB or GB.
634
     * @return 
635
     */
636
    public String getFriendlySize() {
637
        if (filesize != null) {
×
638
            return FileSizeChecker.bytesToHumanReadable(filesize);
×
639
        } else {
640
            return BundleUtil.getStringFromBundle("file.sizeNotAvailable");
×
641
        }
642
    }
643
    
644
    public boolean isRestricted() {
645
        return restricted;
1✔
646
    }
647

648
    
649
    public void setRestricted(boolean restricted) {
650
        this.restricted = restricted;
1✔
651
    }
1✔
652

653
    public ChecksumType getChecksumType() {
654
        return checksumType;
1✔
655
    }
656

657
    public void setChecksumType(ChecksumType checksumType) {
658
        this.checksumType = checksumType;
1✔
659
    }
1✔
660

661
    public String getChecksumValue() {
662
        return this.checksumValue;
1✔
663
    }
664

665
    public void setChecksumValue(String checksumValue) {
666
        this.checksumValue = checksumValue;
1✔
667
    }
1✔
668

669
    public String getOriginalChecksumType() {
670
        return BundleUtil.getStringFromBundle("file.originalChecksumType", Arrays.asList(this.checksumType.toString()) );
×
671
    }
672

673
    public StorageIO<DataFile> getStorageIO() throws IOException {
674
        StorageIO<DataFile> storageIO = DataAccess.getStorageIO(this);
1✔
675
        
676
        if (storageIO == null) {
1✔
677
            throw new IOException("Failed to create storageIO for datafile.");
×
678
        }
679
        
680
        return storageIO; 
1✔
681
    }
682
    
683
    /*
684
        Does the contentType indicate a shapefile?
685
    */
686
    public boolean isShapefileType(){
687
        if (this.contentType==null){
×
688
            return false;
×
689
        }
690
        return ShapefileHandler.SHAPEFILE_FILE_TYPE.equalsIgnoreCase(this.contentType);
×
691
    }
692
    
693
    public boolean isImage() {
694
        // Some browsers (Chrome?) seem to identify FITS files as mime
695
        // type "image/fits" on upload; this is both incorrect (the official
696
        // mime type for FITS is "application/fits", and problematic: then
697
        // the file is identified as an image, and the page will attempt to 
698
        // generate a preview - which of course is going to fail...
699
        if ("image/fits".equalsIgnoreCase(contentType)) {
×
700
            return false;
×
701
        }
702
        // a pdf file is an "image" for practical purposes (we will attempt to 
703
        // generate thumbnails and previews for them)
704
        return (contentType != null && (contentType.startsWith("image/") || contentType.equalsIgnoreCase("application/pdf")));
×
705
    }
706
    
707
    public boolean isFilePackage() {
708
        return DataFileServiceBean.MIME_TYPE_PACKAGE_FILE.equalsIgnoreCase(contentType);
×
709
    }
710

711
    public void setIngestStatus(char ingestStatus) {
712
        this.ingestStatus = ingestStatus; 
×
713
    }    
×
714
   
715
    public boolean isIngestScheduled() {
716
        return (ingestStatus == INGEST_STATUS_SCHEDULED);
×
717
    }
718
    
719
    public boolean isIngestInProgress() {
720
        return ((ingestStatus == INGEST_STATUS_SCHEDULED) || (ingestStatus == INGEST_STATUS_INPROGRESS));
×
721
    }
722
    
723
    public boolean isIngestProblem() {
724
        return (ingestStatus == INGEST_STATUS_ERROR);
×
725
    }
726
    
727
    public void SetIngestScheduled() {
728
        ingestStatus = INGEST_STATUS_SCHEDULED;
×
729
    }
×
730
    
731
    public void SetIngestInProgress() {
732
        ingestStatus = INGEST_STATUS_INPROGRESS;
×
733
    }
×
734
    
735
    public void SetIngestProblem() {
736
        ingestStatus = INGEST_STATUS_ERROR;
×
737
    }
×
738
    
739
    public void setIngestDone() {
740
        ingestStatus = INGEST_STATUS_NONE;
1✔
741
    }
1✔
742
    
743
    public int getIngestStatus() {
744
        return ingestStatus; 
×
745
    }
746
    
747
    public Dataset getThumbnailForDataset() {
748
        return thumbnailForDataset;
×
749
    }
750
    
751
    public void setAsThumbnailForDataset(Dataset dataset) {
752
        thumbnailForDataset = dataset;
×
753
    }
×
754

755
    /*
756
        8/10/2014 - Using the current "open access" url
757
    */
758
    public String getMapItFileDownloadURL(String serverName){
759
        if ((this.getId() == null)||(serverName == null)){
×
760
            return null;
×
761
        }
762
        return serverName + "/api/access/datafile/" + this.getId();
×
763
    }
764
    
765
    /* 
766
     * If this is tabular data, the corresponding dataTable may have a UNF -
767
     * "numeric fingerprint" signature - generated:
768
     */
769
    
770
    public String getUnf() {
771
        if (this.isTabularData()) {
1✔
772
            // (isTabularData() method above verifies that that this file 
773
            // has a datDatable associated with it, so the line below is 
774
            // safe, in terms of a NullPointerException: 
775
            return this.getDataTable().getUnf();
1✔
776
        }
777
        return null; 
×
778
    }
779

780
    public List<AuthenticatedUser> getFileAccessRequesters() {
781
        return fileAccessRequesters;
×
782
    }
783

784
    public void setFileAccessRequesters(List<AuthenticatedUser> fileAccessRequesters) {
785
        this.fileAccessRequesters = fileAccessRequesters;
×
786
    }
×
787

788

789
    public void addFileAccessRequest(FileAccessRequest request) {
790
        if (this.fileAccessRequests == null) {
×
791
            this.fileAccessRequests = new ArrayList<>();
×
792
        }
793

794
        this.fileAccessRequests.add(request);
×
795
    }
×
796

797
    public FileAccessRequest getAccessRequestForAssignee(RoleAssignee roleAssignee) {
798
        if (this.fileAccessRequests == null) {
×
799
            return null;
×
800
        }
801

802
        return this.fileAccessRequests.stream()
×
803
                .filter(fileAccessRequest -> fileAccessRequest.getRequester().equals(roleAssignee) && fileAccessRequest.isStateCreated()).findFirst()
×
804
                .orElse(null);
×
805
    }
806

807
    public boolean removeFileAccessRequest(FileAccessRequest request) {
808
        if (this.fileAccessRequests == null) {
×
809
            return false;
×
810
        }
811

812
        if (request != null) {
×
813
            this.fileAccessRequests.remove(request);
×
814
            return true;
×
815
        }
816

817
        return false;
×
818
    }
819

820
    public boolean containsActiveFileAccessRequestFromUser(RoleAssignee roleAssignee) {
821
        if (this.fileAccessRequests == null) {
×
822
            return false;
×
823
        }
824

825
        Set<AuthenticatedUser> existingUsers = getFileAccessRequests(FileAccessRequest.RequestState.CREATED).stream()
×
826
            .map(FileAccessRequest::getRequester)
×
827
            .collect(Collectors.toSet());
×
828

829
        return existingUsers.contains(roleAssignee);
×
830
    }
831

832
    public boolean isHarvested() {
833
        
834
        Dataset ownerDataset = this.getOwner();
1✔
835
        if (ownerDataset != null) {
1✔
836
            return ownerDataset.isHarvested(); 
1✔
837
        }
838
        return false; 
×
839
    }
840
    
841
    public String getRemoteArchiveURL() {
842
        if (isHarvested()) {
×
843
            Dataset ownerDataset = this.getOwner();
×
844
            return ownerDataset.getRemoteArchiveURL();
×
845
        }
846
        
847
        return null; 
×
848
    }
849
    
850
    public String getHarvestingDescription() {
851
        if (isHarvested()) {
×
852
            Dataset ownerDataset = this.getOwner();
×
853
            return ownerDataset.getHarvestingDescription();
×
854
        }
855
        
856
        return null;
×
857
    }
858
    
859
    @Override
860
    public boolean equals(Object object) {
861
        if (!(object instanceof DataFile)) {
1✔
862
            return false;
×
863
        }
864
        DataFile other = (DataFile) object;
1✔
865
        return Objects.equals(getId(), other.getId());
1✔
866
    }
867

868
    @Override
869
    public int hashCode() {
870
        return super.hashCode();
×
871
    }
872

873
    @Override
874
    protected String toStringExtras() {
875
        FileMetadata fmd = getLatestFileMetadata();
×
876
        return "label:" + (fmd!=null? fmd.getLabel() : "[no metadata]");
×
877
    }
878
        
879
        @Override
880
        public <T> T accept( Visitor<T> v ) {
881
                return v.visit(this);
×
882
        }
883
        
884
    @Override
885
    public String getDisplayName() {
886
       return getLatestFileMetadata().getLabel(); 
1✔
887
    }
888
    
889
    public String getDirectoryLabel() {
890
       return getLatestFileMetadata().getDirectoryLabel();
1✔
891
    }
892
    
893
    @Override 
894
    public String getCurrentName(){
895
        return getLatestFileMetadata().getLabel();
1✔
896
    }
897
    
898
    @Override
899
    public int compareTo(Object o) {
900
        /*
901
         * The primary intent here is to provide ordering by displayName. However, the
902
         * secondary comparison by id is needed to insure that two DataFiles with the
903
         * same displayName aren't considered equal, e.g. in structures that require
904
         * unique keys. See Issues #4287 and #6401.
905
         */
906
        DataFile other = (DataFile) o;
×
907
        int comparison = this.getDisplayName().toUpperCase().compareTo(other.getDisplayName().toUpperCase());
×
908
        if (comparison == 0) {
×
909
            comparison = this.getId().compareTo(other.getId());
×
910
        }
911
        return comparison;
×
912
    }
913
    
914
    /**
915
     * Check if the Geospatial Tag has been assigned to this file
916
     * @return 
917
     */
918
    public boolean hasGeospatialTag(){
919
        if (this.dataFileTags == null){
×
920
            return false;
×
921
        }
922
        for (DataFileTag tag : this.dataFileTags){
×
923
            if (tag.isGeospatialTag()){
×
924
                return true;
×
925
            }
926
        }
×
927
        return false;
×
928
    }
929

930
    
931
    /**
932
     *  Set rootDataFileId
933
     *  @param rootDataFileId
934
     */
935
    public void setRootDataFileId(Long rootDataFileId){
936
        this.rootDataFileId = rootDataFileId;
×
937
    }
×
938

939
    /**
940
     *  Get for rootDataFileId
941
     *  @return Long
942
     */
943
    public Long getRootDataFileId(){
944
        return this.rootDataFileId;
1✔
945
    }
946

947
//    public int getProvCplId() {
948
//        return provCplId;
949
//    }
950
//    
951
//    public void setProvCplId(int cplId) {
952
//        this.provCplId = cplId;
953
//    }
954
    
955
    public String getProvEntityName() {
956
        return provEntityName;
×
957
    }
958
    
959
    public void setProvEntityName(String name) {
960
        this.provEntityName = name;
×
961
    }
×
962
    
963
    /**
964
     *  Set previousDataFileId
965
     *  @param previousDataFileId
966
     */
967
    public void setPreviousDataFileId(Long previousDataFileId){
968
        this.previousDataFileId = previousDataFileId;
×
969
    }
×
970

971
    /**
972
     *  Get for previousDataFileId
973
     *  @return Long
974
     */
975
    public Long getPreviousDataFileId(){
976
        return this.previousDataFileId;
1✔
977
    }
978

979
    public String toPrettyJSON(){
980
        
981
        return serializeAsJSON(true);
×
982
    }
983

984
    public String toJSON(){
985
        
986
        return serializeAsJSON(false);
×
987
    }
988
    
989
    
990
    
991
    public JsonObject asGsonObject(boolean prettyPrint){
992
        
993
        GsonBuilder builder;
994
        if (prettyPrint){  // Add pretty printing
×
995
            builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting();
×
996
        }else{
997
            builder = new GsonBuilder().excludeFieldsWithoutExposeAnnotation();                        
×
998
        }
999
        
1000
        builder.serializeNulls();   // correctly capture nulls
×
1001
        Gson gson = builder.create();
×
1002

1003
        // ----------------------------------
1004
        // serialize this object + add the id
1005
        // ----------------------------------
1006
        JsonElement jsonObj = gson.toJsonTree(this);
×
1007
        jsonObj.getAsJsonObject().addProperty("id", this.getId());
×
1008

1009
        // ----------------------------------
1010
        //  get the FileMetadata object
1011
        // ----------------------------------
1012
        FileMetadata thisFileMetadata = this.getFileMetadata();
×
1013

1014
        // ----------------------------------
1015
        //  Add dataset info
1016
        // ----------------------------------
1017

1018
        Map<String, Object> datasetMap = new HashMap<>();
×
1019
        // expensive call.......bleh!!! 
1020
        // https://github.com/IQSS/dataverse/issues/761, https://github.com/IQSS/dataverse/issues/2110, https://github.com/IQSS/dataverse/issues/3191
1021
        //
1022
        datasetMap.put("title", thisFileMetadata.getDatasetVersion().getTitle());
×
1023
        datasetMap.put("persistentId", getOwner().getGlobalId().asString());
×
1024
        datasetMap.put("url", getOwner().getPersistentURL());
×
1025
        datasetMap.put("version", thisFileMetadata.getDatasetVersion().getSemanticVersion());
×
1026
        datasetMap.put("id", getOwner().getId());
×
1027
        datasetMap.put("isPublished", thisFileMetadata.getDatasetVersion().isReleased());
×
1028
        
1029
        jsonObj.getAsJsonObject().add("dataset",  gson.toJsonTree(datasetMap));
×
1030
       
1031
        // ----------------------------------
1032
        //  Add dataverse info
1033
        // ----------------------------------
1034
        Map<String, Object> dataverseMap = new HashMap<>();
×
1035
        Dataverse dv = this.getOwner().getOwner();
×
1036
        
1037
        dataverseMap.put("name", dv.getName());
×
1038
        dataverseMap.put("alias", dv.getAlias());
×
1039
        dataverseMap.put("id", dv.getId()); 
×
1040

1041
        jsonObj.getAsJsonObject().add("dataverse",  gson.toJsonTree(dataverseMap));
×
1042
        
1043
        // ----------------------------------
1044
        //  Add label (filename), description, and categories from the FileMetadata object
1045
        // ----------------------------------
1046

1047
        jsonObj.getAsJsonObject().addProperty("filename", thisFileMetadata.getLabel());
×
1048
        jsonObj.getAsJsonObject().addProperty("description", thisFileMetadata.getDescription());
×
1049
        jsonObj.getAsJsonObject().add("categories", 
×
1050
                            gson.toJsonTree(thisFileMetadata.getCategoriesByName())
×
1051
                    );
1052

1053
        // ----------------------------------        
1054
        // Tags
1055
        // ----------------------------------               
1056
        jsonObj.getAsJsonObject().add("tags", gson.toJsonTree(getTagLabels()));
×
1057

1058
        // ----------------------------------        
1059
        // Checksum
1060
        // ----------------------------------
1061
        Map<String, String> checkSumMap = new HashMap<>();
×
1062
        checkSumMap.put("type", getChecksumType().toString());
×
1063
        checkSumMap.put("value", getChecksumValue());
×
1064
        
1065
        JsonElement checkSumJSONMap = gson.toJsonTree(checkSumMap);
×
1066
        
1067
        jsonObj.getAsJsonObject().add("checksum", checkSumJSONMap);
×
1068
        
1069
        return jsonObj.getAsJsonObject();
×
1070
        
1071
    }
1072
    
1073
    /**
1074
     * 
1075
     * @param prettyPrint
1076
     * @return 
1077
     */
1078
    private String serializeAsJSON(boolean prettyPrint){
1079
        
1080
        JsonObject fullFileJSON = asGsonObject(prettyPrint);
×
1081
              
1082
        //return fullFileJSON.
1083
        return fullFileJSON.toString();
×
1084
        
1085
    }
1086
    
1087
    public String getPublicationDateFormattedYYYYMMDD() {
1088
        if (getPublicationDate() != null){
1✔
1089
                   return new SimpleDateFormat("yyyy-MM-dd").format(getPublicationDate()); 
×
1090
        }
1091
        return null;
1✔
1092
    }
1093
    
1094
    public String getCreateDateFormattedYYYYMMDD() {
1095
        if (getCreateDate() != null){
1✔
1096
                   return new SimpleDateFormat("yyyy-MM-dd").format(getCreateDate()); 
×
1097
        }
1098
        return null;
1✔
1099
    }
1100
    
1101
    @Override
1102
    public String getTargetUrl() {
1103
        return DataFile.TARGET_URL;
×
1104
    }
1105

1106
    private boolean tagExists(String tagLabel) {
1107
        for (DataFileTag dataFileTag : dataFileTags) {
×
1108
            if (dataFileTag.getTypeLabel().equals(tagLabel)) {
×
1109
                return true;
×
1110
            }
1111
        }
×
1112
        return false;
×
1113
    }
1114
} // end of class
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc