[geary/wip/766133-gnotification: 12/15] Make it easier to obtain folders from path objects from Geary.Account



commit f7488453d00464a0782cfe5264750f8c4f2244bf
Author: Michael Gratton <mike vee net>
Date:   Sun Apr 14 20:57:31 2019 +1000

    Make it easier to obtain folders from path objects from Geary.Account
    
    Replace async folder accessors with sync versions, add a means of
    obtaining a folder path from its serialised form.

 src/engine/api/geary-account.vala                  | 62 +++++++++++++++-------
 src/engine/app/app-email-store.vala                | 33 ++++--------
 .../imap-db/search/imap-db-search-folder.vala      |  2 +-
 .../imap-engine/imap-engine-generic-account.vala   | 59 ++++++++++----------
 .../imap-engine/imap-engine-minimal-folder.vala    |  4 +-
 .../imap-engine-revokable-committed-move.vala      |  2 +-
 test/engine/api/geary-account-mock.vala            | 46 ++++++++++------
 7 files changed, 115 insertions(+), 93 deletions(-)
---
diff --git a/src/engine/api/geary-account.vala b/src/engine/api/geary-account.vala
index ae0fc056..41e74cfa 100644
--- a/src/engine/api/geary-account.vala
+++ b/src/engine/api/geary-account.vala
@@ -320,6 +320,48 @@ public abstract class Geary.Account : BaseObject {
     public abstract EmailIdentifier to_email_identifier(GLib.Variant serialised)
         throws EngineError.BAD_PARAMETERS;
 
+    /**
+     * Returns the folder path from its serialised form.
+     *
+     * This is useful for converting a string representation of a
+     * folder path back into an actual instance of a path. This does
+     * not guarantee that the folder represented by the path will
+     * exist.
+     *
+     * @see FolderPath.to_variant
+     * @throws EngineError.BAD_PARAMETERS when the variant is not the
+     * have the correct type or if no folder root with an appropriate
+     * label exists.
+     */
+    public abstract FolderPath to_folder_path(GLib.Variant serialised)
+        throws EngineError.BAD_PARAMETERS;
+
+    /**
+     * Determines if a folder is known to the engine.
+     *
+     * This method only considers currently known folders, it does not
+     * check the remote to see if a previously folder exists.
+     */
+    public virtual bool has_folder(FolderPath path) {
+        try {
+            get_folder(path);
+            return true;
+        } catch (EngineError.NOT_FOUND err) {
+            return false;
+        }
+    }
+
+    /**
+     * Returns the folder represented by a specific path.
+     *
+     * This method only considers currently known folders, it does not
+     * check the remote to see if a previously folder exists.
+     *
+     * @throws EngineError.NOT_FOUND if the folder does not exist.
+     */
+    public abstract Folder get_folder(FolderPath path)
+        throws EngineError.NOT_FOUND;
+
     /**
      * Lists all the currently-available folders found under the parent path
      * unless it's null, in which case it lists all the root folders.  If the
@@ -347,26 +389,6 @@ public abstract class Geary.Account : BaseObject {
      */
     public abstract Geary.ContactStore get_contact_store();
 
-    /**
-     * Returns true if the folder exists.
-     *
-     * This method never throws EngineError.NOT_FOUND.
-     */
-    public abstract async bool folder_exists_async(Geary.FolderPath path, Cancellable? cancellable = null)
-        throws Error;
-
-    /**
-     * Fetches a Folder object corresponding to the supplied path.  If the backing medium does
-     * not have a record of a folder at the path, EngineError.NOT_FOUND will be thrown.
-     *
-     * The same Geary.Folder object (instance) will be returned if the same path is submitted
-     * multiple times.  This means that multiple callers may be holding references to the same
-     * Folders.  This is important when thinking of opening and closing folders and signal
-     * notifications.
-     */
-    public abstract async Geary.Folder fetch_folder_async(Geary.FolderPath path,
-        Cancellable? cancellable = null) throws Error;
-
     /**
      * Returns the folder representing the given special folder type.  If no such folder exists,
      * null is returned.
diff --git a/src/engine/app/app-email-store.vala b/src/engine/app/app-email-store.vala
index a346409b..103fbf05 100644
--- a/src/engine/app/app-email-store.vala
+++ b/src/engine/app/app-email-store.vala
@@ -41,7 +41,7 @@ public class Geary.App.EmailStore : BaseObject {
             foreach (Geary.FolderPath path in folders.get(email)) {
                 Geary.Folder folder;
                 try {
-                    folder = yield account.fetch_folder_async(path, cancellable);
+                    folder = account.get_folder(path);
                 } catch (Error e) {
                     debug("Error getting a folder from path %s: %s", path.to_string(), e.message);
                     continue;
@@ -108,33 +108,23 @@ public class Geary.App.EmailStore : BaseObject {
             emails, cancellable);
     }
 
-    private async Gee.HashMap<Geary.FolderPath, Geary.Folder> get_folder_instances_async(
-        Gee.Collection<Geary.FolderPath> paths, Cancellable? cancellable) throws Error {
-        Gee.HashMap<Geary.FolderPath, Geary.Folder> folders
-            = new Gee.HashMap<Geary.FolderPath, Geary.Folder>();
-        foreach (Geary.FolderPath path in paths) {
-            Geary.Folder folder = yield account.fetch_folder_async(path, cancellable);
-            folders.set(path, folder);
-        }
-        return folders;
-    }
-
-    private Geary.FolderPath? next_folder_for_operation(AsyncFolderOperation operation,
-        Gee.MultiMap<Geary.FolderPath, Geary.EmailIdentifier> folders_to_ids,
-        Gee.Map<Geary.FolderPath, Geary.Folder> folders) throws Error {
+    private FolderPath?
+        next_folder_for_operation(AsyncFolderOperation operation,
+                                  Gee.MultiMap<FolderPath,EmailIdentifier> folders_to_ids)
+        throws GLib.Error {
         bool best_is_open = false;
         int best_count = 0;
         Geary.FolderPath? best = null;
         foreach (Geary.FolderPath path in folders_to_ids.get_keys()) {
-            assert(folders.has_key(path));
-            if (!folders.get(path).get_type().is_a(operation.folder_type))
+            Folder folder = this.account.get_folder(path);
+            if (!folder.get_type().is_a(operation.folder_type))
                 continue;
 
             int count = folders_to_ids.get(path).size;
             if (count == 0)
                 continue;
 
-            if (folders.get(path).get_open_state() == Geary.Folder.OpenState.REMOTE) {
+            if (folder.get_open_state() == Geary.Folder.OpenState.REMOTE) {
                 if (!best_is_open) {
                     best_is_open = true;
                     best_count = 0;
@@ -167,12 +157,9 @@ public class Geary.App.EmailStore : BaseObject {
 
         Gee.MultiMap<Geary.FolderPath, Geary.EmailIdentifier> folders_to_ids
             = Geary.Collection.reverse_multi_map<Geary.EmailIdentifier, Geary.FolderPath>(ids_to_folders);
-        Gee.HashMap<Geary.FolderPath, Geary.Folder> folders
-            = yield get_folder_instances_async(folders_to_ids.get_keys(), cancellable);
-
         Geary.FolderPath? path;
-        while ((path = next_folder_for_operation(operation, folders_to_ids, folders)) != null) {
-            Geary.Folder folder = folders.get(path);
+        while ((path = next_folder_for_operation(operation, folders_to_ids)) != null) {
+            Geary.Folder folder = this.account.get_folder(path);
             Gee.Collection<Geary.EmailIdentifier> ids = folders_to_ids.get(path);
             assert(ids.size > 0);
 
diff --git a/src/engine/imap-db/search/imap-db-search-folder.vala 
b/src/engine/imap-db/search/imap-db-search-folder.vala
index 5a2b84e1..0081f349 100644
--- a/src/engine/imap-db/search/imap-db-search-folder.vala
+++ b/src/engine/imap-db/search/imap-db-search-folder.vala
@@ -336,7 +336,7 @@ private class Geary.ImapDB.SearchFolder : Geary.SearchFolder, Geary.FolderSuppor
             = Geary.Collection.reverse_multi_map<Geary.EmailIdentifier, Geary.FolderPath>(ids_to_folders);
 
         foreach (Geary.FolderPath path in folders_to_ids.get_keys()) {
-            Geary.Folder folder = yield account.fetch_folder_async(path, cancellable);
+            Geary.Folder folder = account.get_folder(path);
             Geary.FolderSupport.Remove? remove = folder as Geary.FolderSupport.Remove;
             if (remove == null)
                 continue;
diff --git a/src/engine/imap-engine/imap-engine-generic-account.vala 
b/src/engine/imap-engine/imap-engine-generic-account.vala
index acb92b48..6e4c4bb9 100644
--- a/src/engine/imap-engine/imap-engine-generic-account.vala
+++ b/src/engine/imap-engine/imap-engine-generic-account.vala
@@ -434,6 +434,34 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
         throw new EngineError.BAD_PARAMETERS("Unknown serialised type: %c", type);
     }
 
+    /** {@inheritDoc} */
+    public override FolderPath to_folder_path(GLib.Variant serialised)
+        throws EngineError.BAD_PARAMETERS {
+        FolderPath? path = null;
+        try {
+            path = this.local.imap_folder_root.from_variant(serialised);
+        } catch (EngineError.BAD_PARAMETERS err) {
+            path = this.local_folder_root.from_variant(serialised);
+        }
+        return path;
+    }
+
+    /** {@inheritDoc} */
+    public override Folder get_folder(FolderPath path)
+        throws EngineError.NOT_FOUND {
+        Folder? folder = this.folder_map.get(path);
+        if (folder == null) {
+            folder = this.local_only.get(path);
+            if (folder == null) {
+                throw new EngineError.NOT_FOUND(
+                    "Folder not found: %s", path.to_string()
+                );
+            }
+        }
+        return folder;
+    }
+
+    /** {@inheritDoc} */
     public override Gee.Collection<Geary.Folder> list_matching_folders(Geary.FolderPath? parent)
         throws Error {
         check_open();
@@ -461,33 +489,6 @@ private abstract class Geary.ImapEngine.GenericAccount : Geary.Account {
         return local.contact_store;
     }
 
-    /** {@inheritDoc} */
-    public override async bool folder_exists_async(Geary.FolderPath path,
-                                                   Cancellable? cancellable = null)
-        throws Error {
-        check_open();
-        return this.local_only.has_key(path) || this.folder_map.has_key(path);
-    }
-
-    /** {@inheritDoc} */
-    public override async Geary.Folder fetch_folder_async(Geary.FolderPath path,
-                                                          Cancellable? cancellable = null)
-        throws Error {
-        check_open();
-
-        Geary.Folder? folder = this.local_only.get(path);
-        if (folder == null) {
-            folder = this.folder_map.get(path);
-
-            if (folder == null) {
-                throw new EngineError.NOT_FOUND(
-                    "Folder not found: %s", path.to_string()
-                );
-            }
-        }
-        return folder;
-    }
-
     public override async Geary.Folder get_required_special_folder_async(Geary.SpecialFolderType special,
         Cancellable? cancellable) throws Error {
         if (!(special in get_supported_special_folders())) {
@@ -1125,9 +1126,7 @@ internal class Geary.ImapEngine.LoadFolders : AccountOperation {
                 path = this.local.imap_folder_root.copy(path);
                 if (path != null) {
                     try {
-                        Geary.Folder target = yield generic.fetch_folder_async(
-                            path, cancellable
-                        );
+                        Geary.Folder target = generic.get_folder(path);
                         added_specials.set(type, target);
                     } catch (Error err) {
                         debug(
diff --git a/src/engine/imap-engine/imap-engine-minimal-folder.vala 
b/src/engine/imap-engine/imap-engine-minimal-folder.vala
index e6e4e3d7..bbe2bded 100644
--- a/src/engine/imap-engine/imap-engine-minimal-folder.vala
+++ b/src/engine/imap-engine/imap-engine-minimal-folder.vala
@@ -1272,7 +1272,7 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
                          Geary.FolderPath destination,
                          GLib.Cancellable? cancellable = null)
         throws GLib.Error {
-        Geary.Folder target = yield this._account.fetch_folder_async(destination);
+        Geary.Folder target = this._account.get_folder(destination);
         yield copy_email_uids_async(to_copy, destination, cancellable);
         this._account.update_folder(target);
     }
@@ -1321,7 +1321,7 @@ private class Geary.ImapEngine.MinimalFolder : Geary.Folder, Geary.FolderSupport
         if (prepare.prepared_for_move == null || prepare.prepared_for_move.size == 0)
             return null;
 
-        Geary.Folder target = yield this._account.fetch_folder_async(destination);
+        Geary.Folder target = this._account.get_folder(destination);
         return new RevokableMove(
             _account, this, target, prepare.prepared_for_move
         );
diff --git a/src/engine/imap-engine/imap-engine-revokable-committed-move.vala 
b/src/engine/imap-engine/imap-engine-revokable-committed-move.vala
index 54431035..386186c0 100644
--- a/src/engine/imap-engine/imap-engine-revokable-committed-move.vala
+++ b/src/engine/imap-engine/imap-engine-revokable-committed-move.vala
@@ -40,7 +40,7 @@ private class Geary.ImapEngine.RevokableCommittedMove : Revokable {
 
             notify_revoked();
 
-            Geary.Folder target = yield this.account.fetch_folder_async(this.destination);
+            Geary.Folder target = this.account.get_folder(this.destination);
             this.account.update_folder(target);
         } finally {
             if (session != null) {
diff --git a/test/engine/api/geary-account-mock.vala b/test/engine/api/geary-account-mock.vala
index fb1189a6..ce5304e3 100644
--- a/test/engine/api/geary-account-mock.vala
+++ b/test/engine/api/geary-account-mock.vala
@@ -135,6 +135,36 @@ public class Geary.MockAccount : Account, MockObject {
         }
     }
 
+    public override FolderPath to_folder_path(GLib.Variant serialised)
+        throws EngineError.BAD_PARAMETERS {
+        try {
+            return object_or_throw_call(
+                "to_folder_path",
+                { box_arg(serialised) },
+                new EngineError.BAD_PARAMETERS("Mock error")
+            );
+        } catch (EngineError.BAD_PARAMETERS err) {
+            throw err;
+        } catch (GLib.Error err) {
+            return new FolderRoot("#mock", false);
+        }
+    }
+
+    public override Folder get_folder(FolderPath path)
+        throws EngineError.NOT_FOUND {
+        try {
+            return object_or_throw_call(
+                "get_folder",
+                { path },
+                new EngineError.NOT_FOUND("Mock error")
+            );
+        } catch (EngineError.NOT_FOUND err) {
+            throw err;
+        } catch (GLib.Error err) {
+            return new MockFolder(null, null, null, SpecialFolderType.NONE, null);
+        }
+    }
+
     public override Gee.Collection<Folder> list_folders() throws Error {
         return object_call<Gee.Collection<Folder>>(
             "list_folders", {}, Gee.List.empty<Folder>()
@@ -145,22 +175,6 @@ public class Geary.MockAccount : Account, MockObject {
         return new MockContactStore();
     }
 
-    public override async bool folder_exists_async(FolderPath path,
-                                                   Cancellable? cancellable = null)
-        throws Error {
-        return boolean_call("folder_exists_async", {path, cancellable}, false);
-    }
-
-    public override async Folder fetch_folder_async(FolderPath path,
-                                                    Cancellable? cancellable = null)
-    throws Error {
-        return object_or_throw_call<Folder>(
-            "fetch_folder_async",
-            {path, cancellable},
-            new EngineError.NOT_FOUND("Mock call")
-        );
-    }
-
     public override Folder? get_special_folder(SpecialFolderType special)
         throws Error {
         return object_call<Folder?>(


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]