Merge remote-tracking branch 'upstream/develop' into
[pub/Android/ownCloud.git] / src / com / owncloud / android / operations / MoveFileOperation.java
index f1a3f9f..63856c3 100644 (file)
 
 package com.owncloud.android.operations;
 
-import java.io.File;
-import java.io.IOException;
-
 import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.lib.common.OwnCloudClient;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
-import com.owncloud.android.lib.resources.files.RenameRemoteFileOperation;
+import com.owncloud.android.lib.resources.files.MoveRemoteFileOperation;
 import com.owncloud.android.operations.common.SyncOperation;
-import com.owncloud.android.utils.FileStorageUtils;
-import com.owncloud.android.utils.Log_OC;
 
 import android.accounts.Account;
 
@@ -39,11 +34,11 @@ import android.accounts.Account;
  */
 public class MoveFileOperation extends SyncOperation {
     
-    private static final String TAG = MoveFileOperation.class.getSimpleName();
+    //private static final String TAG = MoveFileOperation.class.getSimpleName();
+    
+    private String mSrcPath;
+    private String mTargetParentPath;
     
-    private String mPath;
-    private Account mAccount;
-    private String mNewParentPath;
     private OCFile mFile;
 
     
@@ -55,18 +50,16 @@ public class MoveFileOperation extends SyncOperation {
      * @param newParentPath     Path to the folder where the file will be moved into. 
      * @param account           OwnCloud account containing both the file and the target folder 
      */
-    public MoveFileOperation(String path, String newParentPath, Account account) {
-        mPath = path;
-        mNewParentPath = newParentPath;
-        mAccount = account;
+    public MoveFileOperation(String srcPath, String targetParentPath, Account account) {
+        mSrcPath = srcPath;
+        mTargetParentPath = targetParentPath;
+        if (!mTargetParentPath.endsWith(OCFile.PATH_SEPARATOR)) {
+            mTargetParentPath += OCFile.PATH_SEPARATOR;
+        }
+        
         mFile = null;
     }
   
-    public OCFile getFile() {
-        return mFile;
-    }
-    
-    
     /**
      * Performs the operation.
      * 
@@ -76,120 +69,35 @@ public class MoveFileOperation extends SyncOperation {
     protected RemoteOperationResult run(OwnCloudClient client) {
         RemoteOperationResult result = null;
         
-        mFile = getStorageManager().getFileByPath(mPath);
-        
-        // check if the new name is valid in the local file system
-        try {
-            String parentPath = (new File(mFile.getRemotePath())).getParent();
-            parentPath = (parentPath.endsWith(OCFile.PATH_SEPARATOR)) 
-                    ? parentPath 
-                    : parentPath + OCFile.PATH_SEPARATOR;
-            
-            String mNewPath = mNewParentPath + mFile.getFileName();
-            if (mFile.isFolder() && !mNewPath.endsWith(OCFile.PATH_SEPARATOR)) {
-                mNewPath += OCFile.PATH_SEPARATOR;
-            }
-
-            // check local overwrite
-            if (getStorageManager().getFileByPath(mPath) != null) {
-                return new RemoteOperationResult(ResultCode.INVALID_OVERWRITE);
-            }
-            
-            MoveRemoteFileOperation operation = new MoveRemoteFileOperation(
-                    mFile.getRemotePath(), 
-                    mNewPath, 
-                    mFile.isFolder()
-            );
-            result = operation.execute(client);
-
-            if (result.isSuccess()) {
-                if (mFile.isFolder()) {
-                    saveLocalDirectory();
-
-                } else {
-                    saveLocalFile();
-                }
-            }
-            
-        } catch (IOException e) {
-            Log_OC.e(TAG, "Move " + mFile.getRemotePath() + " to " + 
-                    (mNewParentPath==null) + ": " + 
-                    ((result!= null) ? result.getLogMessage() : ""), e);
+        /// 1. check move validity
+        if (mTargetParentPath.startsWith(mSrcPath)) {
+            return new RemoteOperationResult(ResultCode.INVALID_MOVE_INTO_DESCENDANT);
         }
-
-        return result;
-    }
-
-    
-    private void saveLocalDirectory() {
-        getStorageManager().moveFolder(mFile, mNewParentPath);
-        String localPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile);
-        File localDir = new File(localPath);
-        if (localDir.exists()) {
-            localDir.renameTo(new File(FileStorageUtils.getSavePath(mAccount.name) + mNewParentPath));
-            // TODO - if renameTo fails, children files that are already down will result unlinked
+        mFile = getStorageManager().getFileByPath(mSrcPath);
+        if (mFile == null) {
+            return new RemoteOperationResult(ResultCode.FILE_NOT_FOUND);
         }
-    }
-
-    private void saveLocalFile() {
-        mFile.setFileName(mNewName);
         
-        // try to rename the local copy of the file
-        if (mFile.isDown()) {
-            File f = new File(mFile.getStoragePath());
-            String parentStoragePath = f.getParent();
-            if (!parentStoragePath.endsWith(File.separator))
-                parentStoragePath += File.separator;
-            if (f.renameTo(new File(parentStoragePath + mNewName))) {
-                mFile.setStoragePath(parentStoragePath + mNewName);
-            }
-            // else - NOTHING: the link to the local file is kept although the local name can't be updated
-            // TODO - study conditions when this could be a problem
+        /// 2. remote move
+        String targetPath = mTargetParentPath + mFile.getFileName();
+        if (mFile.isFolder()) {
+            targetPath += OCFile.PATH_SEPARATOR;
         }
+        MoveRemoteFileOperation operation = new MoveRemoteFileOperation(
+                mSrcPath, 
+                targetPath, 
+                false
+        );
+        result = operation.execute(client);
         
-        getStorageManager().saveFile(mFile);
-    }
-
-    /**
-     * Checks if the new name to set is valid in the file system 
-     * 
-     * The only way to be sure is trying to create a file with that name. It's made in the temporal directory
-     * for downloads, out of any account, and then removed. 
-     * 
-     * IMPORTANT: The test must be made in the same file system where files are download. The internal storage
-     * could be formatted with a different file system.
-     * 
-     * TODO move this method, and maybe FileDownload.get***Path(), to a class with utilities specific for the interactions with the file system
-     * 
-     * @return              'True' if a temporal file named with the name to set could be created in the file system where 
-     *                      local files are stored.
-     * @throws IOException  When the temporal folder can not be created.
-     */
-    private boolean isValidNewName() throws IOException {
-        // check tricky names
-        if (mNewName == null || mNewName.length() <= 0 || mNewName.contains(File.separator) || mNewName.contains("%")) { 
-            return false;
-        }
-        // create a test file
-        String tmpFolderName = FileStorageUtils.getTemporalPath("");
-        File testFile = new File(tmpFolderName + mNewName);
-        File tmpFolder = testFile.getParentFile();
-        tmpFolder.mkdirs();
-        if (!tmpFolder.isDirectory()) {
-            throw new IOException("Unexpected error: temporal directory could not be created");
-        }
-        try {
-            testFile.createNewFile();   // return value is ignored; it could be 'false' because the file already existed, that doesn't invalidate the name
-        } catch (IOException e) {
-            Log_OC.i(TAG, "Test for validity of name " + mNewName + " in the file system failed");
-            return false;
-        }
-        boolean result = (testFile.exists() && testFile.isFile());
-        
-        // cleaning ; result is ignored, since there is not much we could do in case of failure, but repeat and repeat...
-        testFile.delete();
+        /// 3. local move
+        if (result.isSuccess()) {
+            getStorageManager().moveLocalFile(mFile, targetPath, mTargetParentPath);
+        } 
+        // TODO handle ResultCode.PARTIAL_MOVE_DONE in client Activity, for the moment
         
         return result;
     }
+    
 
 }