Refactored MoveFileOperation to handle local update after remote move (WIP)
[pub/Android/ownCloud.git] / src / com / owncloud / android / datamodel / FileDataStorageManager.java
index 2f2cf45..5dfdb98 100644 (file)
@@ -41,6 +41,7 @@ import android.content.ContentProviderResult;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
+import android.content.Intent;
 import android.content.OperationApplicationException;
 import android.database.Cursor;
 import android.net.Uri;
 import android.content.OperationApplicationException;
 import android.database.Cursor;
 import android.net.Uri;
@@ -187,6 +188,7 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
         cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
         cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
         cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
+        cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
         
         boolean sameRemotePath = fileExists(file.getRemotePath());
         if (sameRemotePath ||
         
         boolean sameRemotePath = fileExists(file.getRemotePath());
         if (sameRemotePath ||
@@ -287,6 +289,7 @@ public class FileDataStorageManager {
             cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
             cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
             cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
             cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
             cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
             cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
+            cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
 
             boolean existsByPath = fileExists(file.getRemotePath());
             if (existsByPath || fileExists(file.getFileId())) {
 
             boolean existsByPath = fileExists(file.getRemotePath());
             if (existsByPath || fileExists(file.getFileId())) {
@@ -345,6 +348,7 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, folder.isShareByLink() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink());
         cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions());
         cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, folder.isShareByLink() ? 1 : 0);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, folder.getPublicLink());
         cv.put(ProviderTableMeta.FILE_PERMISSIONS, folder.getPermissions());
+        cv.put(ProviderTableMeta.FILE_REMOTE_ID, folder.getRemoteId());
         
         operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
                 withValues(cv).
         
         operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
                 withValues(cv).
@@ -609,6 +613,142 @@ public class FileDataStorageManager {
     }
 
     
     }
 
     
+    //public void moveFolder(OCFile folder, String newPath) {
+    public void moveLocalFile(OCFile file, String targetPath) {
+        // TODO check newPath
+        if (file != null && file.fileExists()) {
+            
+            if (//file.isFolder() && // should work for regular files!! 
+                !OCFile.ROOT_PATH.equals(file.getFileName())) {
+            
+                /// 0. move in local file system 
+                
+                /// 1. get all the descendants in a single QUERY (including the folder)
+                Cursor c = null;
+                if (getContentProviderClient() != null) {
+                    try {
+                        c = getContentProviderClient().query(
+                            ProviderTableMeta.CONTENT_URI, 
+                            null,
+                            ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + 
+                                    ProviderTableMeta.FILE_PATH + " LIKE ? ",
+                            new String[] { 
+                                    mAccount.name, 
+                                    file.getRemotePath() + "%"  
+                            }, 
+                            ProviderTableMeta.FILE_PATH + " ASC "
+                        );
+                    } catch (RemoteException e) {
+                        Log_OC.e(TAG, e.getMessage());
+                    }
+                    
+                } else {
+                    c = getContentResolver().query(
+                        ProviderTableMeta.CONTENT_URI, 
+                        null,
+                        ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + 
+                                ProviderTableMeta.FILE_PATH + " LIKE ? ",
+                        new String[] { 
+                                mAccount.name, 
+                                file.getRemotePath() + "%"  
+                        }, 
+                        ProviderTableMeta.FILE_PATH + " ASC "
+                    );
+                }
+    
+                /// 2. prepare a batch of update operations to change all the descendants
+                ArrayList<ContentProviderOperation> operations = 
+                        new ArrayList<ContentProviderOperation>(c.getCount());
+                if (c.moveToFirst()) {
+                    int lengthOfOldPath = file.getRemotePath().length();
+                    String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
+                    int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
+                    do {
+                        ContentValues cv = new ContentValues(); // keep construction in the loop
+                        OCFile child = createFileInstance(c);
+                        cv.put(
+                            ProviderTableMeta.FILE_PATH, 
+                            targetPath + child.getRemotePath().substring(lengthOfOldPath)
+                        );
+                        if (child.getStoragePath() != null && 
+                                child.getStoragePath().startsWith(defaultSavePath)) {
+                            // update link to downloaded content - but local move is not done here!
+                            cv.put(
+                                ProviderTableMeta.FILE_STORAGE_PATH, 
+                                defaultSavePath + targetPath + 
+                                    child.getStoragePath().substring(lengthOfOldStoragePath)
+                            );
+                        }
+                        operations.add(
+                            ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
+                                withValues(cv).
+                                withSelection(  
+                                        ProviderTableMeta._ID + "=?", 
+                                        new String[] { String.valueOf(child.getFileId()) }
+                                        )
+                                .build());
+                        
+                    } while (c.moveToNext());
+                }
+                c.close();
+    
+                /// 3. apply updates in batch
+                try {
+                    if (getContentResolver() != null) {
+                        getContentResolver().applyBatch(MainApp.getAuthority(), operations);
+    
+                    } else {
+                        getContentProviderClient().applyBatch(operations);
+                    }
+    
+                } catch (Exception e) {
+                    Log_OC.e(
+                        TAG, 
+                        "Fail to update " + file.getFileId() + " and descendants in database", 
+                        e
+                    );
+                }
+                
+            }
+        }
+        
+        /*
+        private void saveLocalDirectory() {
+             * TODO implement local movement of folder
+            getStorageManager().moveFolder(mFile, mNewPath);
+            String localPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile);
+            File localDir = new File(localPath);
+            if (localDir.exists()) {
+                localDir.renameTo(new File(FileStorageUtils.getSavePath(mAccount.name) + mNewPath));
+                // TODO - if renameTo fails, children files that are already down will result unlinked
+            }
+        }
+        */
+
+        /*
+        private void saveLocalFile() {
+            mFile.setRFileName(mNewName);   <<< NO >
+            
+            // try to move 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())) {
+                    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
+            }
+            
+            getStorageManager().saveFile(mFile);
+        }
+        */
+        
+    }
+    
+    
     private Vector<OCFile> getFolderContent(long parentId) {
 
         Vector<OCFile> ret = new Vector<OCFile>();
     private Vector<OCFile> getFolderContent(long parentId) {
 
         Vector<OCFile> ret = new Vector<OCFile>();
@@ -754,6 +894,7 @@ public class FileDataStorageManager {
                     c.getColumnIndex(ProviderTableMeta.FILE_SHARE_BY_LINK)) == 1 ? true : false);
             file.setPublicLink(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PUBLIC_LINK)));
             file.setPermissions(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PERMISSIONS)));
                     c.getColumnIndex(ProviderTableMeta.FILE_SHARE_BY_LINK)) == 1 ? true : false);
             file.setPublicLink(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PUBLIC_LINK)));
             file.setPermissions(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_PERMISSIONS)));
+            file.setRemoteId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID)));
                     
         }
         return file;
                     
         }
         return file;
@@ -1097,6 +1238,7 @@ public class FileDataStorageManager {
                 cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
                 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
                 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
                 cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
                 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
                 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
+                cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
 
                 boolean existsByPath = fileExists(file.getRemotePath());
                 if (existsByPath || fileExists(file.getFileId())) {
 
                 boolean existsByPath = fileExists(file.getRemotePath());
                 if (existsByPath || fileExists(file.getFileId())) {
@@ -1297,4 +1439,5 @@ public class FileDataStorageManager {
             */
         //}
     }
             */
         //}
     }
+
 }
 }