## KolabMailAccess KolabMailAccess — the Kolab2 PIM email infrastructure |

## Stability Level

Unstable, unless otherwise indicated

## Synopsis

    struct              KolabMailAccessClass;
    gboolean            kolab_mail_access_bringup           (KolabMailAccess *self,
                                                             GCancellable *cancellable,
                                                             GError **err);
    gboolean            kolab_mail_access_configure         (KolabMailAccess *self,
                                                             KolabSettingsHandler *ksettings,
                                                             GError **err);
    gboolean            kolab_mail_access_create_source     (KolabMailAccess *self,
                                                             const gchar *sourcename,
                                                             GCancellable *cancellable,
                                                             GError **err);
    gboolean            kolab_mail_access_delete_by_uid     (KolabMailAccess *self,
                                                             const gchar *uid,
                                                             const gchar *sourcename,
                                                             GCancellable *cancellable,
                                                             GError **err);
    gboolean            kolab_mail_access_delete_handle     (KolabMailAccess *self,
                                                             const KolabMailHandle *kmailhandle,
                                                             GCancellable *cancellable,
                                                             GError **err);
    gboolean            kolab_mail_access_delete_source     (KolabMailAccess *self,
                                                             const gchar *sourcename,
                                                             GCancellable *cancellable,
                                                             GError **err);
    const KolabMailHandle * kolab_mail_access_get_handle    (KolabMailAccess *self,
                                                             const gchar *uid,
                                                             const gchar *sourcename,
                                                             GCancellable *cancellable,
                                                             GError **err);
    KolabMailAccessOpmodeID kolab_mail_access_get_opmode    (KolabMailAccess *self,
                                                             GError **err);
    KolabSettingsHandler * kolab_mail_access_get_settings_handler
                                                            (KolabMailAccess *self);
    GList *             kolab_mail_access_query_changed_uids
                                                            (KolabMailAccess *self,
                                                             const gchar *sourcename,
                                                             const gchar *sexp,
                                                             GCancellable *cancellable,
                                                             GError **err);
    GList *             kolab_mail_access_query_sources     (KolabMailAccess *self,
                                                             GError **err);
    GList *             kolab_mail_access_query_uids        (KolabMailAccess *self,
                                                             const gchar *sourcename,
                                                             const gchar *sexp,
                                                             GError **err);
    gboolean            kolab_mail_access_retrieve_handle   (KolabMailAccess *self,
                                                             const KolabMailHandle *kmailhandle,
                                                             gboolean bulk,
                                                             GCancellable *cancellable,
                                                             GError **err);
    gboolean            kolab_mail_access_set_opmode        (KolabMailAccess *self,
                                                             KolabMailAccessOpmodeID opmode,
                                                             GCancellable *cancellable,
                                                             GError **err);
    gboolean            kolab_mail_access_shutdown          (KolabMailAccess *self,
                                                             GCancellable *cancellable,
                                                             GError **err);
    gboolean            kolab_mail_access_source_fbtrigger_needed
                                                            (KolabMailAccess *self,
                                                             const gchar *sourcename,
                                                             GError **err);
    gboolean            kolab_mail_access_store_handle      (KolabMailAccess *self,
                                                             KolabMailHandle *kmailhandle,
                                                             const gchar *sourcename,
                                                             GCancellable *cancellable,
                                                             GError **err);

## Description

This class is the main Kolab2 PIM email store and server connector. It is comprised of the following main objects

- KolabMailImapClient -- connects with a Kolab2 IMAP server, read-only offline cache
- KolabMailInfoDb -- keeps PIM folder and PIM email metadata
- KolabMailMimeBuilder -- deals with MIME message parts and whole MIME messages
- KolabMailSideCache -- read/write offline cache for PIM folders and PIM emails
- KolabMailSynchronizer -- PIM data (and metadata) synchronization, conflict resolution

KolabMailAccess needs to be configured before operating it. Call `kolab_mail_access_configure()` and supply a KolabSettingsHandler object. This defines the context KolabMailAccess will be working in, i.e. `KOLAB_FOLDER_CONTEXT_CALENDAR` or `KOLAB_FOLDER_CONTEXT_CONTACT` (see KolabFolderContextID).

Operational modes of this class can be switched via calls to `kolab_mail_access_set_opmode()`. Operational modes are defined in KolabMailAccessOpmodeID.

In KolabMailAccess, a "source" means an address book or a calendar. Before storing/retrieving PIM data to/from a source (which is mapped to some specific IMAP folder on the server side), the source needs to either already exist or it must be created.

The query functions may invalidate folder information or KolabMailHandle objects retrieved prior to the query function call. It is probably best not to store KolabMailHandle references outside KolabMailAccess but to get UID lists and get the associated handle by calling `kolab_mail_access_get_handle()` each time a handle is needed for any operation with it. Each call to a query function may add new changed UIDs to an internal list. This list can be retrieved once by calling `kolab_mail_access_query_changed_uids()`. Be sure to take proper care of the UIDs contained therein. A "changed" UID may mean that the corresponding PIM object does no longer exist. A call to `kolab_mail_access_get_handle()` with such a UID will return with a NULL value.

For information about the notions of "complete" and "incomplete" mail handles, see KolabMailHandle. In short, you can use an incomplete handle for deletion operations only. For all else, call `kolab_mail_access_retrieve_handle()` to complete the handle and attach the actual PIM data to it.

KolabMailHandle objects have a notion of being "complete" or "incomplete". In the latter case, they are merely shallow objects with very little information attached to them. Before operating on a KolabMailHandle object, make sure it is complete. An incomplete object can be completed by a call to `kolab_mail_access_retrieve_handle()` which will fetch the actual data from any of the caches within KolabMailAccess. To delete a PIM object, it's KolabMailHandle representation does not need to be completed.

The `kolab_mail_access_store_handle()` operation changes the completeness state of a handle from complete to incomplete, as it strips off the actual PIM data and stores it persistently, and so it does with the handle metadata. This means that before the same handle can be used further, it must be completed again (and may yield different data, e.g. if the PIM data has changed on the server and we're in online operation). This operation takes ownership of the KolabMailHandle object.

## Details

### struct KolabMailAccessClass

    struct KolabMailAccessClass {
    	GObjectClass parent_class;
    };

### kolab_mail_access_bringup ()

    gboolean            kolab_mail_access_bringup           (KolabMailAccess *self,
                                                             GCancellable *cancellable,
                                                             GError **err);

Gets the KolabMailAccess object into operational (offline) mode, bringing up all underlying infrastructure (databases, reality-checks, metadata synchronization etc). Must be called once after object configuration and before any further operation. On success, changes the object status (see KolabMailAccessOpmodeID).

This is a shortcut for `kolab_mail_access_set_opmode()`.

- Opmode precondition: `KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED`
- Opmode postcondition: `KOLAB_MAIL_ACCESS_OPMODE_OFFLINE`

`self` : | a KolabMailAccess instance
`cancellable` : | A cancellation stack
`err` : | a GError object (or NULL)
Returns : | TRUE on success, FALSE otherwise (with `err` set)

### kolab_mail_access_configure ()

    gboolean            kolab_mail_access_configure         (KolabMailAccess *self,
                                                             KolabSettingsHandler *ksettings,
                                                             GError **err);

Configures the object for operation. Must be called once after object instantiation and before any other operation. On success, changes the object status (see KolabMailAccessOpmodeID). The KolabSettingsHandler is passed to all subordinate main objects.

- Opmode precondition: `KOLAB_MAIL_ACCESS_OPMODE_NEW`
- Opmode postcondition: `KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED`

`self` : | a KolabMailAccess instance
`ksettings` : | an already-configured KolabSettingsHandler instance
`err` : | a GError object (or NULL)
Returns : | TRUE on success, FALSE otherwise (with `err` set)

### kolab_mail_access_create_source ()

    gboolean            kolab_mail_access_create_source     (KolabMailAccess *self,
                                                             const gchar *sourcename,
                                                             GCancellable *cancellable,
                                                             GError **err);

Creates a source (address book or calendar) of the given name. A source needs to be created using this function prior to storing a KolabMailHandle into this source. If the `sourcename` supplied already exists, the function simply returns successfully.

If KolabMailAccess is in online operational mode, the source gets created on the Kolab server right away. If that fails or if KolabMailAccess is in offline operational mode, the source gets created in the local cache only and is synchronized with the server at the next synchronization point. If the source was created locally only, you can nonetheless store KolabMailHandle objects in it.

`self` : | a KolabMailAccess instance
`sourcename` : | the name of the source to create
`cancellable` : | A cancellation stack
`err` : | a GError object (or NULL)
Returns : | TRUE on success, FALSE if offline creation failed (with `err` set)

### kolab_mail_access_delete_by_uid ()

    gboolean            kolab_mail_access_delete_by_uid     (KolabMailAccess *self,
                                                             const gchar *uid,
                                                             const gchar *sourcename,
                                                             GCancellable *cancellable,
                                                             GError **err);

Looks up a KolabMailHandle by it's `uid` and deletes the PIM data associated with it. For operational details, see `kolab_mail_access_delete_handle()`.

- Handle precondition: none
- Handle postcondition: invalid

`self` : | a KolabMailAccess instance
`uid` : | the UID of the KolabMailHandle to delete
`sourcename` : | the name of the source to delete an object from
`cancellable` : | A cancellation stack
`err` : | a GError object (or NULL)
Returns : | TRUE on success, FALSE if no PIM object found for `uid` or if offline deletion failed (each with `err` set)

### kolab_mail_access_delete_handle ()

    gboolean            kolab_mail_access_delete_handle     (KolabMailAccess *self,
                                                             const KolabMailHandle *kmailhandle,
                                                             GCancellable *cancellable,
                                                             GError **err);

Deletes the PIM data associated with this KolabMailHandle. The handle does not need to be complete. If in online operational mode, the PIM data is deleted from the server as well as from the local caches. In offline mode, the data is marked for deletion and the UID is no longer returned in any query. Trying to `kolab_mail_access_get_handle()` a deleted UID will result in a NULL return value (with an error set), same holds true for all other operations on that handle, including another attempt to delete the same handle. Make sure to drop all references to a deleted handle you hold (working with non-temporary handle references is not advisable anyway).

In case of online failure, we fall back to offline behaviour. UIDs marked as deleted in the local cache will be deleted from the server at the next chance, that is, when a sync operation is triggerred (i.e. at online->offline or offline->online operational mode switching).

- Handle precondition: none
- Handle postcondition: invalid

`self` : | a KolabMailAccess instance
`kmailhandle` : | the KolabMailHandle to delete
`cancellable` : | A cancellation stack
`err` : | a GError object (or NULL)
Returns : | TRUE on success, FALSE if offline deletion failed (with `err` set)

### kolab_mail_access_delete_source ()

    gboolean            kolab_mail_access_delete_source     (KolabMailAccess *self,
                                                             const gchar *sourcename,
                                                             GCancellable *cancellable,
                                                             GError **err);

Whether or not a free/busy generation trigger needs to be sent to the Kolab server for a given source. A trigger is needed in any event of a change to an event folder (other folders do not need to be triggered since they do not provide free/busy information). Sending the trigger may have been delayed due to offline operation. When going online, triggers for event folders which have seen offline changes need to be sent.

`self` : | a KolabMailAccess instance
`sourcename` : | the name of the source to delete
`err` : | a GError object (or NULL)
Returns : | TRUE if a trigger needs to be sent for a given source, FALSE otherwise

### kolab_mail_access_get_handle ()

    const KolabMailHandle * kolab_mail_access_get_handle    (KolabMailAccess *self,
                                                             const gchar *uid,
                                                             const gchar *sourcename,
                                                             GCancellable *cancellable,
                                                             GError **err);

Gets the KolabMailHandle representing the PIM email associated with `uid`. The handle returned is owned by KolabMailAccess at any time. It may not yet be completed. Some operations work on completed mail handles only. Call the `kolab_mail_access_retrieve_handle()` function to complete an incomplete handle (that is, attach the actual PIM data to it).

If a `sourcename` is supplied, the `uid` is searched for in the named source only, so the return value may be NULL in that case, even if the `uid` in question exists (but in another source).

- Handle precondition: none
- Handle postcondition: may be incomplete

`self` : | a KolabMailAccess instance
`uid` : | the UID to get the KolabMailHandle for
`sourcename` : | the name of an address book or calendar (or NULL)
`cancellable` : | A cancellation stack
`err` : | a GError object (or NULL)
Returns : | A (possibly incomplete) KolabMailHandle on success, NULL otherwise (with `err` set)

### kolab_mail_access_get_opmode ()

    KolabMailAccessOpmodeID kolab_mail_access_get_opmode    (KolabMailAccess *self,
                                                             GError **err);

Gets the operational mode the object is currently in (see KolabMailAccessOpmodeID).

`self` : | a KolabMailAccess instance
`err` : | a GError object (or NULL)
Returns : | The current opmode of the object on success, `KOLAB_MAIL_ACCESS_OPMODE_INVAL` otherwise (with `err` set)

### kolab_mail_access_get_settings_handler ()

    KolabSettingsHandler * kolab_mail_access_get_settings_handler
                                                            (KolabMailAccess *self);

Gets the KolabMailAccess instance's KolabSettingsHandler member. The KolabSettingsHandler must have been set on the KolabMailAccess via it's `kolab_mail_access_configure()` instance. New values set on the settings handler are seen by KolabMailAccess and all of it's main subobjects.

Call `g_object_unref()` on the KolabSettingsHandler instance returned by this function, once it is no longer needed.

`self` : | a KolabMailAccess instance
Returns : | the KolabSettingsHandler member of the KolabMailAccess instance, or NULL (if `kolab_mail_access_configure()` has not been called before)

### kolab_mail_access_query_changed_uids ()

    GList *             kolab_mail_access_query_changed_uids
                                                            (KolabMailAccess *self,
                                                             const gchar *sourcename,
                                                             const gchar *sexp,
                                                             GCancellable *cancellable,
                                                             GError **err);

Aggregates a list of UID strings known to KolabMailAccess for which the PIM data has changed. Changed UIDs will each be reported once only, so make sure to take proper care of these before freeing the list. However, Free the list via a call to `kolab_util_glib_glist_free()` when no longer needed.

UID changes include deletion of PIM objects, so a call to `kolab_mail_access_get_handle()` for a UID reported by this function may yield NULL (which indicates that the UID in question no longer exists).

- List precondition: none
- List postcondition: any previously generated list is invalid

`self` : | a KolabMailAccess instance
`sourcename` : | the name of an address book or calendar (or NULL)
`sexp` : | an EDS search expression string (or NULL)
`cancellable` : | A cancellation stack
`err` : | a GError object (or NULL)
Returns : | A list of UID strings or NULL on success (without `err` set), NULL otherwise (with `err` set)

### kolab_mail_access_query_sources ()

    GList *             kolab_mail_access_query_sources     (KolabMailAccess *self,
                                                             GError **err);

Aggregates a list of source name strings known to KolabMailAccess. Only the source names of the configured context are returned. Any list generated by some previous query will be invalidated. Any source creation or deletion will also invalidate the list returned. Get a fresh list each time you need to operate on one, unless you can be sure there has been no change.

Free the list via a call to `kolab_util_glib_glist_free()` when no longer needed.

- List precondition: none
- List postcondition: any previously generated list is invalid

`self` : | a KolabMailAccess instance
`err` : | a GError object (or NULL)
Returns : | A list of source name strings on success, NULL otherwise (with `err` set)

### kolab_mail_access_query_uids ()

    GList *             kolab_mail_access_query_uids        (KolabMailAccess *self,
                                                             const gchar *sourcename,
                                                             const gchar *sexp,
                                                             GError **err);

Aggregates a list of UID strings known to KolabMailAccess. If `sexp` is NULL, all UIDs are returned. Otherwise, only the UIDs matching the search expression are returned. Any list generated by some previous query will be invalidated. Any handle storing or deletion will also invalidate the list returned. Get a fresh list each time you need to operate on one. Free the list via a call to `kolab_util_glib_glist_free()` when no longer needed.

- List precondition: none
- List postcondition: any previously generated list is invalid

(Searching by `sexp` is not yet implemented, just supply NULL for now.)

`self` : | a KolabMailAccess instance
`sourcename` : | the name of an address book or calendar (or NULL)
`sexp` : | an EDS search expression string (or NULL)
`err` : | a GError object (or NULL)
Returns : | A list of UID strings on success, NULL otherwise (with `err` set)

### kolab_mail_access_retrieve_handle ()

    gboolean            kolab_mail_access_retrieve_handle   (KolabMailAccess *self,
                                                             const KolabMailHandle *kmailhandle,
                                                             gboolean bulk,
                                                             GCancellable *cancellable,
                                                             GError **err);

Retrieves the actual PIM data for a KolabMailHandle. The PIM data is read from the KolabMailAccess offline caches. (TODO need to check whether we should poll the server for updated PIM data for this UID if in online mode.) The retrieved PIM data is attached to the mail handle in Kolab format.

Within this operation, Kolab payload data is converted to Evolution/EDS format. This means that this function may return unsuccessfully with a conversion error set.

- Handle precondition: none
- Handle postcondition: complete

`self` : | a KolabMailAccess instance
`kmailhandle` : | the KolabMailHandle to retrieve PIM data for
`bulk` : | Whether or not this is a mass operation
`cancellable` : | A cancellation stack
`err` : | a GError object (or NULL)
Returns : | TRUE on success, FALSE if reading or converting the PIM data failed (with `err` set)

### kolab_mail_access_set_opmode ()

    gboolean            kolab_mail_access_set_opmode        (KolabMailAccess *self,
                                                             KolabMailAccessOpmodeID opmode,
                                                             GCancellable *cancellable,
                                                             GError **err);

Sets the operational mode for the object. To set an operational mode, an internal opmode transition function is called. If the transition went on successfully, the object's state is changed. The transition functions do have side effects (changing state of the underlying infrastructure). On success, changes the object status (see KolabMailAccessOpmodeID).

Setting an opmode KolabMailAccess is already in is a no-op and the function returns successfully.

Allowed transitions are:

- `KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED` --> `KOLAB_MAIL_ACCESS_OPMODE_OFFLINE`
- `KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED` --> `KOLAB_MAIL_ACCESS_OPMODE_ONLINE`
- `KOLAB_MAIL_ACCESS_OPMODE_OFFLINE` --> `KOLAB_MAIL_ACCESS_OPMODE_ONLINE`
- `KOLAB_MAIL_ACCESS_OPMODE_ONLINE` --> `KOLAB_MAIL_ACCESS_OPMODE_OFFLINE`
- `KOLAB_MAIL_ACCESS_OPMODE_ONLINE` --> `KOLAB_MAIL_ACCESS_OPMODE_SHUTDOWN`
- `KOLAB_MAIL_ACCESS_OPMODE_OFFLINE` --> `KOLAB_MAIL_ACCESS_OPMODE_SHUTDOWN`
- `KOLAB_MAIL_ACCESS_OPMODE_SHUTDOWN` --> `KOLAB_MAIL_ACCESS_OPMODE_CONFIGURED`

(The 'SHUTDOWN --> CONFIGURED' transition type is not currently implemented.)

`self` : | a KolabMailAccess instance
`opmode` : | The operational mode to switch to (see KolabMailAccessOpmodeID)
`cancellable` : | A cancellation stack
`err` : | a GError object (or NULL)
Returns : | TRUE on success, FALSE otherwise (with `err` set)

### kolab_mail_access_shutdown ()

    gboolean            kolab_mail_access_shutdown          (KolabMailAccess *self,
                                                             GCancellable *cancellable,
                                                             GError **err);

Shuts down the KolabMailAccess object from any operational mode, bringing down and synchronizing the entire underlying infrastructure. Must be called before object destruction. No further operation on the object is valid unless `kolab_mail_access_bringup()` is called again. On success, changes the object status (see KolabMailAccessOpmodeID).

This is a shortcut for `kolab_mail_access_set_opmode()`.

- Opmode precondition: `KOLAB_MAIL_ACCESS_OPMODE_ONLINE` or `KOLAB_MAIL_ACCESS_OPMODE_OFFLINE`
- Opmode postcondition: `KOLAB_MAIL_ACCESS_OPMODE_SHUTDOWN`

`self` : | a KolabMailAccess instance
`cancellable` : | A cancellation stack
`err` : | a GError object (or NULL)
Returns : | TRUE on success, FALSE otherwise (with `err` set)

### kolab_mail_access_source_fbtrigger_needed ()

    gboolean            kolab_mail_access_source_fbtrigger_needed
                                                            (KolabMailAccess *self,
                                                             const gchar *sourcename,
                                                             GError **err);

### kolab_mail_access_store_handle ()

    gboolean            kolab_mail_access_store_handle      (KolabMailAccess *self,
                                                             KolabMailHandle *kmailhandle,
                                                             const gchar *sourcename,
                                                             GCancellable *cancellable,
                                                             GError **err);

Persistently stores the the PIM email data represented by KolabMailHandle. If KolabMailAccess is in online operational mode, the data gets stored on the Kolab server right away. If that fails or if KolabMailAccess is in offline operational mode, the data gets cached locally for later synchronization with the server.

To store a newly created KolabMailHandle, a `sourcename` must be supplied as the initial destination for the handle.

If a `sourcename` is supplied, the PIM data gets stored in the named source. In case the KolabMailHandle already carries source information which differs from the one supplied with `sourcename`, it means we're moving to a different address book or calendar. The UID in question will be removed from the previously associated source in this case. The destination source must already exist for this function to complete. If the source does not yet exist, create it with `kolab_mail_access_create_source()`. If the operation went on successfully, the KolabMailHandle carries the new `sourcename`.

In order to store changes in PIM data, you'll need to get the Evolution data from the handle, apply the changes, create a new handle from that, and store that new handle. Existing data will then be dropped by KolabMailAccess, just make sure to keep the UID intact (otherwise, the object will be stored as new).

Within this operation, Evolution/EDS payload data is converted to Kolab format. This means that this function may return unsuccessfully with a conversion error set.

On success, KolabMailAccess takes ownership of the KolabMailHandle supplied. Do not try to `g_object_unref()` a mail handle which KolabMailAccess has taken ownership of. A successfully stored-away handle becomes invalid (this is, an invalid pointer). Be VERY sure to get a new handle via `kolab_mail_access_get_handle()` before trying any subsequent operation on it!

- Handle precondition: must be complete
- Handle postcondition: now INVALID and owned by KolabMailAccess

`self` : | a KolabMailAccess instance
`kmailhandle` : | the KolabMailHandle to store
`sourcename` : | the name of an address book or calendar (or NULL)
`cancellable` : | A cancellation stack
`err` : | a GError object (or NULL)
Returns : | TRUE on success, FALSE if local caching or conversion of the data failed (with `err` set)

## See Also

KolabMailImapClient, KolabMailInfoDb, KolabMailMimeBuilder, KolabMailSideCache, KolabMailSynchronizer, KolabMailHandle, KolabSettingsHandler