[tx-robot] updated from transifex
[pub/Android/ownCloud.git] / src / com / owncloud / android / operations / SynchronizeFileOperation.java
index 72cb22b..bc0caf1 100644 (file)
@@ -1,6 +1,10 @@
-/* ownCloud Android client application
+/**
+ *   ownCloud Android client application
+ *
+ *   @author David A. Velasco
+ *   @author masensio
  *   Copyright (C) 2012 Bartek Przybylski
- *   Copyright (C) 2012-2014 ownCloud Inc.
+ *   Copyright (C) 2015 ownCloud Inc.
  *
  *   This program is free software: you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
@@ -36,9 +40,6 @@ import android.content.Intent;
 
 /**
  * Remote operation performing the read of remote file in the ownCloud server.
- * 
- * @author David A. Velasco
- * @author masensio
  */
 
 public class SynchronizeFileOperation extends SyncOperation {
@@ -65,8 +66,8 @@ public class SynchronizeFileOperation extends SyncOperation {
     /**
      * Constructor for "full synchronization mode".
      * 
-     * Uses remotePath to retrieve all the data both in local cache and in the remote OC server when the operation
-     * is executed, instead of reusing {@link OCFile} instances.
+     * Uses remotePath to retrieve all the data both in local cache and in the remote OC server
+     * when the operation is executed, instead of reusing {@link OCFile} instances.
      * 
      * Useful for direct synchronization of a single file.
      * 
@@ -93,17 +94,19 @@ public class SynchronizeFileOperation extends SyncOperation {
 
     
     /**
-     * Constructor allowing to reuse {@link OCFile} instances just queried from local cache or from remote OC server.
+     * Constructor allowing to reuse {@link OCFile} instances just queried from local cache or
+     * from remote OC server.
      * 
-     * Useful to include this operation as part of the synchronization of a folder (or a full account), avoiding the
-     * repetition of fetch operations (both in local database or remote server).
+     * Useful to include this operation as part of the synchronization of a folder
+     * (or a full account), avoiding the repetition of fetch operations (both in local database
+     * or remote server).
      * 
-     * At least one of localFile or serverFile MUST NOT BE NULL. If you don't have none of them, use the other 
-     * constructor.
+     * At least one of localFile or serverFile MUST NOT BE NULL. If you don't have none of them,
+     * use the other constructor.
      * 
      * @param localFile             Data of file (just) retrieved from local cache/database.
-     * @param serverFile            Data of file (just) retrieved from a remote server. If null, will be
-     *                              retrieved from network by the operation when executed.
+     * @param serverFile            Data of file (just) retrieved from a remote server. If null,
+     *                              will be retrieved from network by the operation when executed.
      * @param account               ownCloud account holding the file.
      * @param syncFileContents      When 'true', transference of data will be started by the 
      *                              operation if needed and no conflict is detected.
@@ -121,7 +124,8 @@ public class SynchronizeFileOperation extends SyncOperation {
         if (mLocalFile != null) {
             mRemotePath = mLocalFile.getRemotePath();
             if (mServerFile != null && !mServerFile.getRemotePath().equals(mRemotePath)) {
-                throw new IllegalArgumentException("serverFile and localFile do not correspond to the same OC file");
+                throw new IllegalArgumentException("serverFile and localFile do not correspond" +
+                        " to the same OC file");
             }
         } else if (mServerFile != null) {
             mRemotePath = mServerFile.getRemotePath();
@@ -138,21 +142,24 @@ public class SynchronizeFileOperation extends SyncOperation {
     /**
      * Temporal constructor.
      * 
-     * Extends the previous one to allow constrained synchronizations where uploads are never performed - only
-     * downloads or conflict detection.
+     * Extends the previous one to allow constrained synchronizations where uploads are never
+     * performed - only downloads or conflict detection.
      * 
-     * Do not use unless you are involved in 'folder synchronization' or 'folder download' work in progress.
+     * Do not use unless you are involved in 'folder synchronization' or 'folder download' work
+     * in progress.
      * 
      * TODO Remove when 'folder synchronization' replaces 'folder download'.
      * 
-     * @param localFile             Data of file (just) retrieved from local cache/database. MUSTN't be null.
-     * @param serverFile            Data of file (just) retrieved from a remote server. If null, will be
-     *                              retrieved from network by the operation when executed.
+     * @param localFile             Data of file (just) retrieved from local cache/database.
+     *                              MUSTN't be null.
+     * @param serverFile            Data of file (just) retrieved from a remote server.
+     *                              If null, will be retrieved from network by the operation
+     *                              when executed.
      * @param account               ownCloud account holding the file.
      * @param syncFileContents      When 'true', transference of data will be started by the 
      *                              operation if needed and no conflict is detected.
-     * @param allowUploads          When 'false', uploads to the server are not done; only downloads or conflict
-     *                              detection. 
+     * @param allowUploads          When 'false', uploads to the server are not done;
+     *                              only downloads or conflict detection.
      * @param context               Android context; needed to start transfers.
      */
     public SynchronizeFileOperation(
@@ -200,14 +207,13 @@ public class SynchronizeFileOperation extends SyncOperation {
 
                 /// check changes in server and local file
                 boolean serverChanged = false;
-                /* time for eTag is coming, but not yet
-                    if (mServerFile.getEtag() != null) {
-                        serverChanged = (!mServerFile.getEtag().equals(mLocalFile.getEtag()));
-                    } else { */
-                serverChanged = (
-                    mServerFile.getModificationTimestamp() != mLocalFile.getModificationTimestampAtLastSyncForData()
-                );
-                //}
+                if (mLocalFile.getEtag() == null || mLocalFile.getEtag().length() == 0) {
+                    // file uploaded (null) or downloaded ("") before upgrade to version 1.8.0; check the old condition
+                    serverChanged = mServerFile.getModificationTimestamp() !=
+                            mLocalFile.getModificationTimestampAtLastSyncForData();
+                } else {
+                    serverChanged = (!mServerFile.getEtag().equals(mLocalFile.getEtag()));
+                }
                 boolean localChanged = (
                     mLocalFile.getLocalModificationTimestamp() > mLocalFile.getLastSyncDateForData()
                 );
@@ -216,14 +222,18 @@ public class SynchronizeFileOperation extends SyncOperation {
                 //if (!mLocalFile.getEtag().isEmpty() && localChanged && serverChanged) {
                 if (localChanged && serverChanged) {
                     result = new RemoteOperationResult(ResultCode.SYNC_CONFLICT);
+                    getStorageManager().saveConflict(mLocalFile, mServerFile.getEtag());
 
                 } else if (localChanged) {
                     if (mSyncFileContents && mAllowUploads) {
                         requestForUpload(mLocalFile);
-                        // the local update of file properties will be done by the FileUploader service when the upload finishes
+                        // the local update of file properties will be done by the FileUploader
+                        // service when the upload finishes
                     } else {
-                        // NOTHING TO DO HERE: updating the properties of the file in the server without uploading the contents would be stupid; 
-                        // So, an instance of SynchronizeFileOperation created with syncFileContents == false is completely useless when we suspect
+                        // NOTHING TO DO HERE: updating the properties of the file in the server
+                        // without uploading the contents would be stupid;
+                        // So, an instance of SynchronizeFileOperation created with
+                        // syncFileContents == false is completely useless when we suspect
                         // that an upload is necessary (for instance, in FileObserverService).
                     }
                     result = new RemoteOperationResult(ResultCode.OK);
@@ -232,14 +242,17 @@ public class SynchronizeFileOperation extends SyncOperation {
                     mLocalFile.setRemoteId(mServerFile.getRemoteId());
                     
                     if (mSyncFileContents) {
-                        requestForDownload(mLocalFile); // local, not server; we won't to keep the value of keepInSync!
-                        // the update of local data will be done later by the FileUploader service when the upload finishes
+                        requestForDownload(mLocalFile); // local, not server; we won't to keep
+                        // the value of favorite!
+                        // the update of local data will be done later by the FileUploader
+                        // service when the upload finishes
                     } else {
                         // TODO CHECK: is this really useful in some point in the code?
-                        mServerFile.setKeepInSync(mLocalFile.keepInSync());
+                        mServerFile.setFavorite(mLocalFile.isFavorite());
                         mServerFile.setLastSyncDateForData(mLocalFile.getLastSyncDateForData());
                         mServerFile.setStoragePath(mLocalFile.getStoragePath());
                         mServerFile.setParentId(mLocalFile.getParentId());
+                        mServerFile.setEtag(mLocalFile.getEtag());
                         getStorageManager().saveFile(mServerFile);
 
                     }
@@ -250,12 +263,16 @@ public class SynchronizeFileOperation extends SyncOperation {
                     result = new RemoteOperationResult(ResultCode.OK);
                 }
 
-            } 
+                // safe blanket: sync'ing a not in-conflict file will clean wrong conflict markers in ancestors
+                if (result.getCode() != ResultCode.SYNC_CONFLICT) {
+                    getStorageManager().saveConflict(mLocalFile, null);
+                }
+            }
 
         }
 
-        Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() + ": " 
-                + result.getLogMessage());
+        Log_OC.i(TAG, "Synchronizing " + mAccount.name + ", file " + mLocalFile.getRemotePath() +
+                ": " + result.getLogMessage());
 
         return result;
     }
@@ -270,7 +287,9 @@ public class SynchronizeFileOperation extends SyncOperation {
         Intent i = new Intent(mContext, FileUploader.class);
         i.putExtra(FileUploader.KEY_ACCOUNT, mAccount);
         i.putExtra(FileUploader.KEY_FILE, file);
-        /*i.putExtra(FileUploader.KEY_REMOTE_FILE, mRemotePath);    // doing this we would lose the value of keepInSync in the road, and maybe it's not updated in the database when the FileUploader service gets it!  
+        /*i.putExtra(FileUploader.KEY_REMOTE_FILE, mRemotePath);
+        // doing this we would lose the value of isFavorite in the road, and maybe
+        // it's not updated in the database when the FileUploader service gets it!
         i.putExtra(FileUploader.KEY_LOCAL_FILE, localFile.getStoragePath());*/
         i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
         i.putExtra(FileUploader.KEY_FORCE_OVERWRITE, true);