Enforced check of local modification date when synchronizing file contents to avoid...
[pub/Android/ownCloud.git] / src / com / owncloud / android / operations / SynchronizeFolderOperation.java
index f85e4e7..d1dd3c4 100644 (file)
@@ -29,6 +29,7 @@ import java.util.Map;
 import java.util.Vector;
 
 import org.apache.http.HttpStatus;
+import org.apache.jackrabbit.webdav.DavConstants;
 import org.apache.jackrabbit.webdav.MultiStatus;
 import org.apache.jackrabbit.webdav.client.methods.PropFindMethod;
 
@@ -167,7 +168,9 @@ public class SynchronizeFolderOperation extends RemoteOperation {
             Log_OC.d(TAG, "Synchronizing " + mAccount.name + remotePath);
 
             // remote request 
-            query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(remotePath));
+            query = new PropFindMethod(client.getBaseUri() + WebdavUtils.encodePath(remotePath),
+                    DavConstants.PROPFIND_ALL_PROP,
+                    DavConstants.DEPTH_1);
             int status = client.executeMethod(query);
 
             // check and process response
@@ -189,7 +192,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
                 if (status == HttpStatus.SC_NOT_FOUND) {
                     if (mStorageManager.fileExists(mLocalFolder.getFileId())) {
                         String currentSavePath = FileStorageUtils.getSavePath(mAccount.name);
-                        mStorageManager.removeDirectory(mLocalFolder, true, (mLocalFolder.isDown() && mLocalFolder.getStoragePath().startsWith(currentSavePath)));
+                        mStorageManager.removeFolder(mLocalFolder, true, (mLocalFolder.isDown() && mLocalFolder.getStoragePath().startsWith(currentSavePath)));
                     }
                 }
                 result = new RemoteOperationResult(false, status, query.getResponseHeaders());
@@ -251,12 +254,21 @@ public class SynchronizeFolderOperation extends RemoteOperation {
                 mStorageManager.saveFile(remoteFolder);
             }
             
-            mChildren = mStorageManager.getDirectoryContent(mLocalFolder);
+            Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() + " didn't change");
+            mChildren = mStorageManager.getFolderContent(mLocalFolder);
             
         } else {
-            // read info of folder contents
+            Log_OC.d(TAG, "Remote folder " + mLocalFolder.getRemotePath() + " changed - starting update of local data ");
+            
             List<OCFile> updatedFiles = new Vector<OCFile>(dataInServer.getResponses().length - 1);
             List<SynchronizeFileOperation> filesToSyncContents = new Vector<SynchronizeFileOperation>();
+
+            // get current data about local contents of the folder to synchronize
+            List<OCFile> localFiles = mStorageManager.getFolderContent(mLocalFolder);
+            Map<String, OCFile> localFilesMap = new HashMap<String, OCFile>(localFiles.size());
+            for (OCFile file : localFiles) {
+                localFilesMap.put(file.getRemotePath(), file);
+            }
             
             // loop to update every child
             OCFile remoteFile = null, localFile = null;
@@ -267,12 +279,14 @@ public class SynchronizeFolderOperation extends RemoteOperation {
                 remoteFile.setParentId(mLocalFolder.getFileId());
 
                 /// retrieve local data for the read file 
-                localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
+                //localFile = mStorageManager.getFileByPath(remoteFile.getRemotePath());
+                localFile = localFilesMap.remove(remoteFile.getRemotePath());
                 
                 /// add to the remoteFile (the new one) data about LOCAL STATE (not existing in the server side)
                 remoteFile.setLastSyncDateForProperties(mCurrentSyncTime);
                 if (localFile != null) {
-                    // properties of local state are kept unmodified 
+                    // some properties of local state are kept unmodified
+                    remoteFile.setFileId(localFile.getFileId());
                     remoteFile.setKeepInSync(localFile.keepInSync());
                     remoteFile.setLastSyncDateForData(localFile.getLastSyncDateForData());
                     remoteFile.setModificationTimestampAtLastSyncForData(localFile.getModificationTimestampAtLastSyncForData());
@@ -282,7 +296,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
                     remoteFile.setEtag(""); // remote eTag will not be updated unless contents are synchronized (Synchronize[File|Folder]Operation with remoteFile as parameter)
                 }
 
-                /// check and fix, if need, local storage path
+                /// check and fix, if needed, local storage path
                 checkAndFixForeignStoragePath(remoteFile);      // fixing old policy - now local files must be copied into the ownCloud local folder 
                 searchForLocalFileInDefaultPath(remoteFile);    // legacy   
 
@@ -293,7 +307,6 @@ public class SynchronizeFolderOperation extends RemoteOperation {
                                                                                         mStorageManager,
                                                                                         mAccount,       
                                                                                         true, 
-                                                                                        false,          
                                                                                         mContext
                                                                                         );
                     filesToSyncContents.add(operation);
@@ -303,16 +316,17 @@ public class SynchronizeFolderOperation extends RemoteOperation {
             }
 
             // save updated contents in local database; all at once, trying to get a best performance in database update (not a big deal, indeed)
-            mStorageManager.saveFiles(updatedFiles);
+            mStorageManager.saveFolder(remoteFolder, updatedFiles, localFilesMap.values());
 
             // request for the synchronization of file contents AFTER saving current remote properties
             startContentSynchronizations(filesToSyncContents, client);
 
             // removal of obsolete files
-            removeObsoleteFiles();
+            //removeObsoleteFiles();
            
             // must be done AFTER saving all the children information, so that eTag is not updated in the database in case of unexpected exceptions
-            mStorageManager.saveFile(remoteFolder);
+            //mStorageManager.saveFile(remoteFolder);
+            mChildren = updatedFiles;
             
         }
         
@@ -320,31 +334,6 @@ public class SynchronizeFolderOperation extends RemoteOperation {
         
     }
 
-
-    /**
-     *  Removes obsolete children in the folder after saving all the new data.
-     */
-    private void removeObsoleteFiles() {
-        mChildren = mStorageManager.getDirectoryContent(mLocalFolder);
-        OCFile file;
-        for (int i=0; i < mChildren.size(); ) {
-            file = mChildren.get(i);
-            if (file.getLastSyncDateForProperties() != mCurrentSyncTime) {
-                if (file.isDirectory()) {
-                    Log_OC.d(TAG, "removing folder: " + file);
-                    mStorageManager.removeDirectory(file, true, true);
-                } else {
-                    Log_OC.d(TAG, "removing file: " + file);
-                    mStorageManager.removeFile(file, true);
-                }
-                mChildren.remove(i);
-            } else {
-                i++;
-            }
-        }
-    }
-
-
     /**
      * Performs a list of synchronization operations, determining if a download or upload is needed or
      * if exists conflict due to changes both in local and remote contents of the each file.
@@ -468,7 +457,7 @@ public class SynchronizeFolderOperation extends RemoteOperation {
      * @param file      File to associate a possible 'lost' local file.
      */
     private void searchForLocalFileInDefaultPath(OCFile file) {
-        if (file.getStoragePath() == null && !file.isDirectory()) {
+        if (file.getStoragePath() == null && !file.isFolder()) {
             File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
             if (f.exists()) {
                 file.setStoragePath(f.getAbsolutePath());