2121import edu .harvard .iq .dataverse .engine .command .exception .CommandException ;
2222import edu .harvard .iq .dataverse .engine .command .impl .AbstractCreateDatasetCommand ;
2323import edu .harvard .iq .dataverse .engine .command .impl .CreateNewDatasetCommand ;
24+ import edu .harvard .iq .dataverse .engine .command .impl .DeleteDataFileCommand ;
2425import edu .harvard .iq .dataverse .engine .command .impl .RestrictFileCommand ;
2526import edu .harvard .iq .dataverse .engine .command .impl .UpdateDatasetVersionCommand ;
2627import edu .harvard .iq .dataverse .ingest .IngestServiceBean ;
@@ -504,6 +505,18 @@ public boolean runReplaceFromUI_Phase1(Long oldFileId,
504505 if (!this .step_005_loadFileToReplaceById (oldFileId )){
505506 return false ;
506507 }
508+ //Update params to match existing file (except checksum, which should match the new file)
509+ if (fileToReplace != null ) {
510+ String checksum = optionalFileParams .getCheckSum ();
511+ ChecksumType checkSumType = optionalFileParams .getCheckSumType ();
512+ try {
513+ optionalFileParams = new OptionalFileParams (fileToReplace );
514+ optionalFileParams .setCheckSum (checksum , checkSumType );
515+ } catch (DataFileTagException e ) {
516+ // Shouldn't happen since fileToReplace should have valid tags
517+ e .printStackTrace ();
518+ }
519+ }
507520
508521 return this .runAddReplacePhase1 (fileToReplace .getOwner (),
509522 newFileName ,
@@ -574,6 +587,26 @@ private boolean runAddReplacePhase1(Dataset owner,
574587 return false ;
575588 }
576589
590+ // if the fileToReplace hasn't been released,
591+ if (fileToReplace != null && !fileToReplace .isReleased ()) {
592+ DataFile df = finalFileList .get (0 ); // step_055 uses a loop and assumes only one file
593+ // set the replacement file's previous and root datafileIds to match (unless
594+ // they are the defaults)
595+ if (fileToReplace .getPreviousDataFileId () != null ) {
596+ df .setPreviousDataFileId (fileToReplace .getPreviousDataFileId ());
597+ df .setRootDataFileId (fileToReplace .getRootDataFileId ());
598+ }
599+ // Reuse any file PID during a replace operation (if File PIDs are in use)
600+ if (systemConfig .isFilePIDsEnabled ()) {
601+ df .setGlobalId (fileToReplace .getGlobalId ());
602+ df .setGlobalIdCreateTime (fileToReplace .getGlobalIdCreateTime ());
603+ // Should be true or fileToReplace wouldn't have an identifier (since it's not
604+ // yet released in this if statement)
605+ df .setIdentifierRegistered (fileToReplace .isIdentifierRegistered ());
606+ fileToReplace .setGlobalId (null );
607+ }
608+ }
609+
577610 return true ;
578611 }
579612
@@ -1061,16 +1094,6 @@ private boolean step_005_loadFileToReplaceById(Long dataFileId){
10611094 if (!step_015_auto_check_permissions (existingFile .getOwner ())){
10621095 return false ;
10631096 };
1064-
1065-
1066-
1067- // Is the file published?
1068- //
1069- if (!existingFile .isReleased ()){
1070- addError (getBundleErr ("unpublished_file_cannot_be_replaced" ));
1071- return false ;
1072- }
1073-
10741097 // Is the file in the latest dataset version?
10751098 //
10761099 if (!step_007_auto_isReplacementInLatestVersion (existingFile )){
@@ -1532,7 +1555,22 @@ private boolean step_070_run_update_dataset_command(){
15321555 }
15331556
15341557 Command <Dataset > update_cmd ;
1535- update_cmd = new UpdateDatasetVersionCommand (dataset , dvRequest , clone );
1558+ String deleteStorageLocation = null ;
1559+ long deleteFileId =-1 ;
1560+ if (isFileReplaceOperation ()) {
1561+ List <FileMetadata > filesToDelete = new ArrayList <FileMetadata >();
1562+ filesToDelete .add (fileToReplace .getFileMetadata ());
1563+
1564+ if (!fileToReplace .isReleased ()) {
1565+ //If file is only in draft version, also need to delete the physical file
1566+ deleteStorageLocation = fileService .getPhysicalFileToDelete (fileToReplace );
1567+ deleteFileId =fileToReplace .getId ();
1568+ }
1569+ //Adding the file to the delete list for the command will delete this filemetadata and, if the file hasn't been released, the datafile itself.
1570+ update_cmd = new UpdateDatasetVersionCommand (dataset , dvRequest , filesToDelete , clone );
1571+ } else {
1572+ update_cmd = new UpdateDatasetVersionCommand (dataset , dvRequest , clone );
1573+ }
15361574 ((UpdateDatasetVersionCommand ) update_cmd ).setValidateLenient (true );
15371575
15381576 try {
@@ -1554,89 +1592,23 @@ private boolean step_070_run_update_dataset_command(){
15541592 this .addErrorSevere ("add.add_file_error (see logs)" );
15551593 logger .severe (ex .getMessage ());
15561594 return false ;
1557- }
1558- return true ;
1559- }
1560-
1561-
1562- /**
1563- * Go through the working DatasetVersion and remove the
1564- * FileMetadata of the file to replace
1565- *
1566- * @return
1567- */
1568- private boolean step_085_auto_remove_filemetadata_to_replace_from_working_version (){
1569-
1570- msgt ("step_085_auto_remove_filemetadata_to_replace_from_working_version 1" );
1571-
1572- if (!isFileReplaceOperation ()){
1573- // Shouldn't happen!
1574- this .addErrorSevere (getBundleErr ("only_replace_operation" ) + " (step_085_auto_remove_filemetadata_to_replace_from_working_version" );
1575- return false ;
1576- }
1577- msg ("step_085_auto_remove_filemetadata_to_replace_from_working_version 2" );
1578-
1579- if (this .hasError ()){
1580- return false ;
15811595 }
1582-
1583-
1584- msgt ("File to replace getId: " + fileToReplace .getId ());
1585-
1586- Iterator <FileMetadata > fmIt = workingVersion .getFileMetadatas ().iterator ();
1587- msgt ("Clear file to replace" );
1588- int cnt = 0 ;
1589- while (fmIt .hasNext ()) {
1590- cnt ++;
1591-
1592- FileMetadata fm = fmIt .next ();
1593- msg (cnt + ") next file: " + fm );
1594- msg (" getDataFile().getId(): " + fm .getDataFile ().getId ());
1595- if (fm .getDataFile ().getId () != null ) {
1596- if (Objects .equals (fm .getDataFile ().getId (), fileToReplace .getId ())) {
1597- msg ("Let's remove it!" );
1598-
1599- // If this is a tabular data file with a UNF, we'll need
1600- // to recalculate the version UNF, once the file is removed:
1601-
1602- boolean recalculateUNF = !StringUtils .isEmpty (fm .getDataFile ().getUnf ());
1603-
1604- if (workingVersion .getId () != null ) {
1605- // If this is an existing draft (i.e., this draft version
1606- // is already saved in the dataset, we'll also need to remove this filemetadata
1607- // explicitly:
1608- msg (" this is an existing draft version..." );
1609- fileService .removeFileMetadata (fm );
1610-
1611- // remove the filemetadata from the list of filemetadatas
1612- // attached to the datafile object as well, for a good
1613- // measure:
1614- fileToReplace .getFileMetadatas ().remove (fm );
1615- // (and yes, we can do .remove(fm) safely - if this released
1616- // file is part of an existing draft, we know that the
1617- // filemetadata object also exists in the database, and thus
1618- // has the id, and can be identified unambiguously.
1619- }
1620-
1621- // and remove it from the list of filemetadatas attached
1622- // to the version object, via the iterator:
1623- fmIt .remove ();
1624-
1625- if (recalculateUNF ) {
1626- msg ("recalculating the UNF" );
1627- ingestService .recalculateDatasetVersionUNF (workingVersion );
1628- msg ("UNF recalculated: " +workingVersion .getUNF ());
1629- }
1630-
1631- return true ;
1596+ //Sanity check
1597+ if (isFileReplaceOperation ()) {
1598+ if (deleteStorageLocation != null ) {
1599+ // Finalize the delete of the physical file
1600+ // (File service will double-check that the datafile no
1601+ // longer exists in the database, before proceeding to
1602+ // delete the physical file)
1603+ try {
1604+ fileService .finalizeFileDelete (deleteFileId , deleteStorageLocation );
1605+ } catch (IOException ioex ) {
1606+ logger .warning ("Failed to delete the physical file associated with the deleted datafile id="
1607+ + deleteFileId + ", storage location: " + deleteStorageLocation );
16321608 }
16331609 }
16341610 }
1635-
1636- msg ("No matches found!" );
1637- addErrorSevere (getBundleErr ("failed_to_remove_old_file_from_dataset" ));
1638- runMajorCleanup ();
1639- return false ;
1611+ return true ;
16401612 }
16411613
16421614
@@ -1711,13 +1683,6 @@ private boolean step_080_run_update_dataset_command_for_replace(){
17111683 return false ;
17121684 }
17131685
1714- // -----------------------------------------------------------
1715- // Remove the "fileToReplace" from the current working version
1716- // -----------------------------------------------------------
1717- if (!step_085_auto_remove_filemetadata_to_replace_from_working_version ()){
1718- return false ;
1719- }
1720-
17211686 // -----------------------------------------------------------
17221687 // Set the "root file ids" and "previous file ids"
17231688 // THIS IS A KEY STEP - SPLIT IT OUT
@@ -1727,26 +1692,27 @@ private boolean step_080_run_update_dataset_command_for_replace(){
17271692 // -----------------------------------------------------------
17281693
17291694
1730- /*
1731- Check the root file id on fileToReplace, updating it if necessary
1732- */
1733- if (fileToReplace .getRootDataFileId ().equals (DataFile .ROOT_DATAFILE_ID_DEFAULT )){
1695+ if (fileToReplace .isReleased ()) {
1696+ /*
1697+ * Check the root file id on fileToReplace, updating it if necessary
1698+ */
1699+ if (fileToReplace .getRootDataFileId ().equals (DataFile .ROOT_DATAFILE_ID_DEFAULT )) {
17341700
1735- fileToReplace .setRootDataFileId (fileToReplace .getId ());
1736- fileToReplace = fileService .save (fileToReplace );
1737- }
1738-
1739- /*
1740- Go through the final file list, settting the rootFileId and previousFileId
1741- */
1742- for (DataFile df : finalFileList ){
1743- df .setPreviousDataFileId (fileToReplace .getId ());
1744-
1745- df .setRootDataFileId (fileToReplace .getRootDataFileId ());
1746-
1747- }
1701+ fileToReplace .setRootDataFileId (fileToReplace .getId ());
1702+ fileToReplace = fileService .save (fileToReplace );
1703+ }
1704+
1705+ /*
1706+ * Go through the final file list, settting the rootFileId and previousFileId
1707+ */
1708+ for (DataFile df : finalFileList ) {
1709+ df .setPreviousDataFileId (fileToReplace .getId ());
1710+
1711+ df .setRootDataFileId (fileToReplace .getRootDataFileId ());
17481712
1749- // Call the update dataset command
1713+ }
1714+ }
1715+ // Call the update dataset command which will delete the replaced filemetadata and file in needed (if file is not released)
17501716 //
17511717 return step_070_run_update_dataset_command ();
17521718
0 commit comments