diff src/main/java/edu/harvard/iq/dataverse/DataFile.java @ 10:a50cf11e5178

Rewrite LGDataverse completely upgrading to dataverse4.0
author Zoe Hong <zhong@mpiwg-berlin.mpg.de>
date Tue, 08 Sep 2015 17:00:21 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/edu/harvard/iq/dataverse/DataFile.java	Tue Sep 08 17:00:21 2015 +0200
@@ -0,0 +1,606 @@
+package edu.harvard.iq.dataverse;
+
+import edu.harvard.iq.dataverse.DatasetVersion.VersionState;
+import edu.harvard.iq.dataverse.api.WorldMapRelatedData;
+import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
+import edu.harvard.iq.dataverse.dataaccess.DataAccess;
+import edu.harvard.iq.dataverse.dataaccess.DataAccessObject;
+import edu.harvard.iq.dataverse.ingest.IngestReport;
+import edu.harvard.iq.dataverse.ingest.IngestRequest;
+import edu.harvard.iq.dataverse.util.FileUtil;
+import edu.harvard.iq.dataverse.util.ShapefileHandler;
+import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Objects;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.Files;
+import javax.persistence.Entity;
+import javax.persistence.OneToMany;
+import javax.persistence.OneToOne;
+import javax.persistence.CascadeType;
+import javax.persistence.Column;
+import javax.persistence.JoinColumn;
+import javax.persistence.JoinTable;
+import javax.persistence.ManyToMany;
+import javax.persistence.NamedQueries;
+import javax.persistence.NamedQuery;
+import javax.validation.constraints.Pattern;
+import org.hibernate.validator.constraints.NotBlank;
+
+/**
+ *
+ * @author gdurand
+ */
+@NamedQueries({
+	@NamedQuery( name="DataFile.removeFromDatasetVersion",
+		query="DELETE FROM FileMetadata f WHERE f.datasetVersion.id=:versionId and f.dataFile.id=:fileId")
+})
+@Entity
+public class DataFile extends DvObject {
+    private static final long serialVersionUID = 1L;
+    
+    public static final char INGEST_STATUS_NONE = 65;
+    public static final char INGEST_STATUS_SCHEDULED = 66;
+    public static final char INGEST_STATUS_INPROGRESS = 67;
+    public static final char INGEST_STATUS_ERROR = 68; 
+    
+    private String name;
+    
+    @NotBlank
+    @Column( nullable = false )
+    @Pattern(regexp = "^.*/.*$", message = "Content-Type must contain a slash")
+    private String contentType;
+    
+    @Column( nullable = false )
+    private String fileSystemName;
+    
+    @Column( nullable = false )
+    private String md5;
+
+    @Column(nullable=true)
+    private Long filesize;      // Number of bytes in file.  Allows 0 and null, negative numbers not permitted
+
+    private boolean restricted;
+    
+    /*
+        Tabular (formerly "subsettable") data files have DataTable objects
+        associated with them:
+    */
+    
+    @OneToMany(mappedBy = "dataFile", cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
+    private List<DataTable> dataTables;
+    
+    @OneToMany(mappedBy = "dataFile", cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
+    private List<IngestReport> ingestReports;
+    
+    @OneToOne(mappedBy = "dataFile", cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
+    private IngestRequest ingestRequest;
+    
+    @OneToMany(mappedBy = "dataFile", orphanRemoval = true, cascade = {CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
+    private List<DataFileTag> dataFileTags;
+    
+    @OneToMany(mappedBy="dataFile", cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
+    private List<FileMetadata> fileMetadatas;
+    
+    @OneToMany(mappedBy="dataFile", cascade={CascadeType.REMOVE, CascadeType.MERGE, CascadeType.PERSIST})
+    private List<GuestbookResponse> guestbookResponses;
+
+    public List<GuestbookResponse> getGuestbookResponses() {
+        return guestbookResponses;
+    }
+
+    public void setGuestbookResponses(List<GuestbookResponse> guestbookResponses) {
+        this.guestbookResponses = guestbookResponses;
+    }
+    
+    private char ingestStatus = INGEST_STATUS_NONE; 
+    
+    @OneToOne(mappedBy = "thumbnailFile")
+    private Dataset thumbnailForDataset;
+    
+
+    public DataFile() {
+        this.fileMetadatas = new ArrayList<>();
+    }    
+
+    public DataFile(String contentType) {
+        this.contentType = contentType;
+        this.fileMetadatas = new ArrayList<>();
+    }
+    
+    // The dvObject field "name" should not be used in
+    // datafile objects.
+    // The file name must be stored in the file metadata.
+    @Deprecated
+    public DataFile(String name, String contentType) {
+        this.name = name;
+        this.contentType = contentType;
+        this.fileMetadatas = new ArrayList<>();
+    }    
+    
+    @Override
+    public boolean isEffectivelyPermissionRoot() {
+        return false;
+    }
+    
+    public List<DataTable> getDataTables() {
+        return dataTables;
+    }
+
+    public void setDataTables(List<DataTable> dataTables) {
+        this.dataTables = dataTables;
+    }
+    
+    public DataTable getDataTable() {
+        if ( getDataTables() != null && getDataTables().size() > 0 ) {
+            return getDataTables().get(0);
+        } else {
+            return null;
+        }
+    }
+
+    public void setDataTable(DataTable dt) {
+        if (this.getDataTables() == null) {
+            this.setDataTables( new ArrayList() );
+        } else {
+            this.getDataTables().clear();
+        }
+
+        this.getDataTables().add(dt);
+    }
+    
+    public List<DataFileTag> getTags() {
+        return dataFileTags;
+    }
+    
+    public void setTags(List<DataFileTag> dataFileTags) {
+        this.dataFileTags = dataFileTags;
+    }
+    
+    public void addTag(DataFileTag tag) {
+        if (dataFileTags == null) {
+            dataFileTags = new ArrayList<>();
+        } 
+
+        dataFileTags.add(tag);
+    }
+    
+    public List<FileMetadata> getFileMetadatas() {
+        return fileMetadatas;
+    }
+
+    public void setFileMetadatas(List<FileMetadata> fileMetadatas) {
+        this.fileMetadatas = fileMetadatas;
+    }
+    
+    public IngestReport getIngestReport() {
+        if ( ingestReports != null && ingestReports.size() > 0 ) {
+            return ingestReports.get(0);
+        } else {
+            return null;
+        }
+    }
+
+    public void setIngestReport(IngestReport report) {
+        if (ingestReports == null) {
+            ingestReports = new ArrayList();
+        } else {
+            ingestReports.clear();
+        }
+
+        ingestReports.add(report);
+    }
+    
+    public IngestRequest getIngestRequest() {
+        return ingestRequest;
+    }
+    
+    public void setIngestRequest(IngestRequest ingestRequest) {
+        this.ingestRequest = ingestRequest;
+    }
+    
+    public String getIngestReportMessage() {
+        if ( ingestReports != null && ingestReports.size() > 0 ) {
+            if (ingestReports.get(0).getReport() != null && !"".equals(ingestReports.get(0).getReport())) {
+                return ingestReports.get(0).getReport();
+            }
+        }
+        return "Ingest failed. No further information is available.";
+    }
+    public boolean isTabularData() {
+        return getDataTables() != null && getDataTables().size() > 0; 
+    }
+    
+    public String getOriginalFileFormat() {
+        if (isTabularData()) {
+            DataTable dataTable = getDataTable();
+            if (dataTable != null) {
+                return dataTable.getOriginalFileFormat();
+            }
+        }
+        return null;
+    }
+
+    /*
+     * A user-friendly version of the "original format":
+     */
+    public String getOriginalFormatLabel() {
+        return FileUtil.getUserFriendlyOriginalType(this);
+    }
+   
+    // The dvObject field "name" should not be used in
+    // datafile objects.
+    // The file name must be stored in the file metadata.
+    @Deprecated
+    public String getName() {
+        return name;
+    }
+
+    @Deprecated
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getContentType() {
+        return contentType;
+    }
+
+    public void setContentType(String contentType) {
+        this.contentType = contentType;
+    }
+
+    public String getFriendlyType() {
+        return FileUtil.getUserFriendlyFileType(this);
+    }
+    
+    @Override
+    public Dataset getOwner() {
+        return (Dataset) super.getOwner();
+    }
+
+    public void setOwner(Dataset dataset) {
+        super.setOwner(dataset);
+    }
+    
+    public String getFileSystemName() {
+        return this.fileSystemName;
+    }
+
+    public void setFileSystemName(String fileSystemName) {
+        this.fileSystemName = fileSystemName;
+    }
+    
+    public String getDescription() {
+        FileMetadata fmd = getLatestFileMetadata();
+        
+        if (fmd == null) {
+            return null;
+        }
+        return fmd.getDescription();
+    }
+
+    public void setDescription(String description) {
+        FileMetadata fmd = getLatestFileMetadata();
+        
+        if (fmd != null) {
+            fmd.setDescription(description);
+        }
+    }
+    
+    public FileMetadata getFileMetadata() {
+        return getLatestFileMetadata();
+    }
+    
+    private FileMetadata getLatestFileMetadata() {
+        FileMetadata fmd = null;
+
+        // for newly added or harvested, just return the one fmd
+        if (fileMetadatas.size() == 1) {
+            return fileMetadatas.get(0);
+        }
+        
+        for (FileMetadata fileMetadata : fileMetadatas) {
+            // if it finds a draft, return it
+            if (fileMetadata.getDatasetVersion().getVersionState().equals(VersionState.DRAFT)) {
+                return fileMetadata;
+            }            
+            
+            // otherwise return the one with the latest version number
+            if (fmd == null || fileMetadata.getDatasetVersion().getVersionNumber().compareTo( fmd.getDatasetVersion().getVersionNumber() ) > 0 ) {
+                fmd = fileMetadata;
+            } else if ((fileMetadata.getDatasetVersion().getVersionNumber().compareTo( fmd.getDatasetVersion().getVersionNumber())==0 )&& 
+                   ( fileMetadata.getDatasetVersion().getMinorVersionNumber().compareTo( fmd.getDatasetVersion().getMinorVersionNumber()) > 0 )   )
+                fmd = fileMetadata;
+        }
+        return fmd;
+    }
+    
+    /**
+     * Get property filesize, number of bytes
+     * @return value of property filesize.
+     */
+    public long getFilesize() {
+        if (this.filesize == null) {
+            // -1 means "unknown"
+            return -1;
+        } 
+        return this.filesize;
+    }
+
+    /**
+     * Set property filesize in bytes
+     * 
+     * Allow nulls, but not negative numbers.
+     * 
+     * @param filesize new value of property filesize.
+     */
+    public void setFilesize(long filesize) {
+        if (filesize < 0){
+            return;
+        }
+       this.filesize = filesize;
+    }
+
+    /**
+     * Converts the stored size of the file in bytes to 
+     * a user-friendly value in KB, MB or GB.
+     */
+    public String getFriendlySize() {
+        return FileUtil.getFriendlySize(filesize);
+    }
+
+    public boolean isRestricted() {
+        return restricted;
+    }
+
+    public void setRestricted(boolean restricted) {
+        this.restricted = restricted;
+    }
+
+
+    public String getmd5() { 
+        return this.md5; 
+    }
+    
+    public void setmd5(String md5) { 
+        this.md5 = md5; 
+    }
+
+    public Path getFileSystemLocation() {
+        // TEMPORARY HACK!
+        // (only used in batch ingest testing -- L.A. 4.0 beta)
+        if (this.fileSystemName != null && this.fileSystemName.startsWith("/")) {
+            return Paths.get(this.fileSystemName);
+        }
+        
+        Path studyDirectoryPath = this.getOwner().getFileSystemDirectory();
+        if (studyDirectoryPath == null) {
+            return null;
+        }
+        String studyDirectory = studyDirectoryPath.toString();
+ 
+        return Paths.get(studyDirectory, this.fileSystemName);
+    }
+    
+    public DataAccessObject getAccessObject() throws IOException {
+        DataAccessObject dataAccess =  DataAccess.createDataAccessObject(this);
+        
+        if (dataAccess == null) {
+            throw new IOException("Failed to create access object for datafile.");
+        }
+        
+        return dataAccess; 
+    }
+    
+    public Path getSavedOriginalFile() {
+       
+        if (!this.isTabularData() || this.fileSystemName == null) {
+            return null; 
+        }
+        
+        Path studyDirectoryPath = this.getOwner().getFileSystemDirectory();
+        if (studyDirectoryPath == null) {
+            return null;
+        }
+        String studyDirectory = studyDirectoryPath.toString();
+ 
+        Path savedOriginal = Paths.get(studyDirectory, "_" + this.fileSystemName);
+        if (Files.exists(savedOriginal)) {
+            return savedOriginal;
+        }
+        return null; 
+    }
+    
+    public String getFilename() {
+        String studyDirectory = this.getOwner().getFileSystemDirectory().toString();
+ 
+        if (studyDirectory == null || this.fileSystemName == null || this.fileSystemName.equals("")) {
+            return null;
+        }
+        String fileSystemPath = studyDirectory + "/" + this.fileSystemName;
+        return fileSystemPath.replaceAll("/", "%2F");
+    }
+    
+    /*
+        Does the contentType indicate a shapefile?
+    */
+    public boolean isShapefileType(){
+        if (this.contentType==null){
+            return false;
+        }
+        return ShapefileHandler.SHAPEFILE_FILE_TYPE.equalsIgnoreCase(this.contentType);
+    }
+    
+    public boolean isImage() {
+        // Some browsers (Chrome?) seem to identify FITS files as mime
+        // type "image/fits" on upload; this is both incorrect (the official
+        // mime type for FITS is "application/fits", and problematic: then
+        // the file is identified as an image, and the page will attempt to 
+        // generate a preview - which of course is going to fail...
+        if ("image/fits".equalsIgnoreCase(contentType)) {
+            return false;
+        }
+        // a pdf file is an "image" for practical purposes (we will attempt to 
+        // generate thumbnails and previews for them)
+        return (contentType != null && (contentType.startsWith("image/") || contentType.equalsIgnoreCase("application/pdf")));
+    }
+   
+    public boolean isIngestScheduled() {
+        return (ingestStatus == INGEST_STATUS_SCHEDULED);
+    }
+    
+    public boolean isIngestInProgress() {
+        return ((ingestStatus == INGEST_STATUS_SCHEDULED) || (ingestStatus == INGEST_STATUS_INPROGRESS));
+    }
+    
+    public boolean isIngestProblem() {
+        return (ingestStatus == INGEST_STATUS_ERROR);
+    }
+    
+    public void SetIngestScheduled() {
+        ingestStatus = INGEST_STATUS_SCHEDULED;
+    }
+    
+    public void SetIngestInProgress() {
+        ingestStatus = INGEST_STATUS_INPROGRESS;
+    }
+    
+    public void SetIngestProblem() {
+        ingestStatus = INGEST_STATUS_ERROR;
+    }
+    
+    public void setIngestDone() {
+        ingestStatus = INGEST_STATUS_NONE;
+    }
+    
+    public int getIngestStatus() {
+        return ingestStatus; 
+    }
+    
+    public Dataset getThumbnailForDataset() {
+        return thumbnailForDataset;
+    }
+    
+    public void setAsThumbnailForDataset(Dataset dataset) {
+        thumbnailForDataset = dataset;
+    }
+    
+    /**
+     * URL to use with the WorldMapRelatedData API
+     * Used within dataset.xhtml
+     * 
+     * @param dataverseUserID
+     * @return URL for "Map It" functionality
+     */
+    public String getMapItURL(Long dataverseUserID){
+        if (dataverseUserID==null){
+            return null;
+        }
+        return WorldMapRelatedData.getMapItURL(this.getId(), dataverseUserID);
+    }
+        
+    /*
+        8/10/2014 - Using the current "open access" url
+    */
+    public String getMapItFileDownloadURL(String serverName){
+        if ((this.getId() == null)||(serverName == null)){
+            return null;
+        }        
+        return serverName + "/api/access/datafile/" + this.getId();
+    }
+    
+    /* 
+     * If this is tabular data, the corresponding dataTable may have a UNF -
+     * "numeric fingerprint" signature - generated:
+     */
+    
+    public String getUnf() {
+        if (this.isTabularData()) {
+            // (isTabularData() method above verifies that that this file 
+            // has a datDatable associated with it, so the line below is 
+            // safe, in terms of a NullPointerException: 
+            return this.getDataTable().getUnf();
+        }
+        return null; 
+    }
+    
+
+    @ManyToMany
+    @JoinTable(name = "fileaccessrequests",
+    joinColumns = @JoinColumn(name = "datafile_id"),
+    inverseJoinColumns = @JoinColumn(name = "authenticated_user_id"))
+    private List<AuthenticatedUser> fileAccessRequesters;
+
+    public List<AuthenticatedUser> getFileAccessRequesters() {
+        return fileAccessRequesters;
+    }
+
+    public void setFileAccessRequesters(List<AuthenticatedUser> fileAccessRequesters) {
+        this.fileAccessRequesters = fileAccessRequesters;
+    }
+    
+        
+    public boolean isHarvested() {
+        // TODO: 
+        // alternatively, we can determine whether this is a harvested file
+        // by looking at the storage identifier of the physical file; 
+        // if it's something that's not a filesystem path (URL, etc.) - 
+        // then it's a harvested object. 
+        // -- L.A. 4.0 
+        Dataset ownerDataset = this.getOwner();
+        if (ownerDataset != null) {
+            return ownerDataset.isHarvested(); 
+        }
+        return false; 
+    }
+    
+    public String getRemoteArchiveURL() {
+        if (isHarvested()) {
+            Dataset ownerDataset = this.getOwner();
+            return ownerDataset.getRemoteArchiveURL();
+        }
+        
+        return null; 
+    }
+    
+    public String getHarvestingDescription() {
+        if (isHarvested()) {
+            Dataset ownerDataset = this.getOwner();
+            return ownerDataset.getHarvestingDescription();
+        }
+        
+        return null;
+    }
+    
+    @Override
+    public boolean equals(Object object) {
+        if (!(object instanceof DataFile)) {
+            return false;
+        }
+        DataFile other = (DataFile) object;
+        return Objects.equals(getId(), other.getId());
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode();
+    }
+
+    @Override
+    protected String toStringExtras() {
+        return "name:" + getName();
+    }
+	
+	@Override
+	public <T> T accept( Visitor<T> v ) {
+		return v.visit(this);
+	}
+        
+    public String getDisplayName() {
+        // @todo should we show the published version label instead?
+        // currently this method is not being used
+        return getLatestFileMetadata().getLabel();
+    }
+}