aboutsummaryrefslogblamecommitdiffstats
path: root/addressbook/backend/pas/pas-backend.c
blob: acc6ed2a2cbe2f9088ba093155d76e0d03d5c1da (plain) (tree)
1
2
3
4
5
6
7
8
9
                                                                           
  
          
                                  
  
                               

   
                   
                        
                        
 




                                  







                                              
                                  
 

                                           
 
                    

 
                                                   
                                                      
                                                  
 


                                                               
                                                                     
 
                                                                     
 
                                                                            















                                                              
                                                                    
 
                                                                      

 











                                                                        
                                                                              


    


                                                     


                                                    
                                                           
 
                                                                         
 
                                                                               












                                                                        
                                                                              












                                                                             
                                                                                   












                                                                      
                                                                            












                                                                       
                                                                             












                                                                                                   
                                                                                












                                                                                                   
                                                                                      












                                                                                                      
                                                                              












                                                                              
                                                                                    












                                                                                 
                                                                                       

 










                                                                                       
                                                                                             

 
















                                                                      

                                                                       




































                                                                                             



                                                                                                         






















































                                                                                   

                          





                                                                     
   
        
                                                                          
                                                                           
 

                                                                   
 
                                                                       
 
                                                                               

 













                                                                               
    

                                               
 
                                                    

                                              
                                                                          
 
                                                                       

 





                                                              
                                                                                    
 
                                                                                  

 







                                                               
    
                                                                   
 

                                                    
















                                                                       

 


                                      






















                                                        




                                               
                                   
 

                                                        
                                              
 



                                                    








                                                                                  




                        
     

                           
                              

                     
                                  
                                                 







                                                                 

                  
                                                                                      



                    
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
 * Author:
 *   Nat Friedman (nat@ximian.com)
 *
 * Copyright 2000, Ximian, Inc.
 */

#include <config.h>
#include "pas-backend.h"
#include "pas-marshal.h"

struct _PASBackendPrivate {
    GList *clients;
    gboolean loaded, writable;
};

/* Signal IDs */
enum {
    LAST_CLIENT_GONE,
    LAST_SIGNAL
};

static guint pas_backend_signals[LAST_SIGNAL];

static GObjectClass *parent_class;

gboolean
pas_backend_construct (PASBackend *backend)
{
    return TRUE;
}

GNOME_Evolution_Addressbook_BookListener_CallStatus
pas_backend_load_uri (PASBackend             *backend,
              const char             *uri)
{
    g_return_val_if_fail (backend != NULL, FALSE);
    g_return_val_if_fail (PAS_IS_BACKEND (backend), FALSE);
    g_return_val_if_fail (uri != NULL, FALSE);
    g_return_val_if_fail (backend->priv->loaded == FALSE, FALSE);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->load_uri != NULL);

    return (* PAS_BACKEND_GET_CLASS (backend)->load_uri) (backend, uri);
}

/**
 * pas_backend_get_uri:
 * @backend: An addressbook backend.
 * 
 * Queries the URI that an addressbook backend is serving.
 * 
 * Return value: URI for the backend.
 **/
const char *
pas_backend_get_uri (PASBackend *backend)
{
    g_return_val_if_fail (backend != NULL, NULL);
    g_return_val_if_fail (PAS_IS_BACKEND (backend), NULL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->get_uri != NULL);

    return (* PAS_BACKEND_GET_CLASS (backend)->get_uri) (backend);
}


void
pas_backend_create_card (PASBackend *backend,
             PASBook    *book,
             PASCreateCardRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL && req->vcard != NULL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->create_card != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->create_card) (backend, book, req);
}

void
pas_backend_remove_cards (PASBackend *backend,
              PASBook *book,
              PASRemoveCardsRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL && req->ids != NULL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->remove_cards != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->remove_cards) (backend, book, req);
}

void
pas_backend_modify_card (PASBackend *backend,
             PASBook *book,
             PASModifyCardRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL && req->vcard != NULL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->modify_card != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->modify_card) (backend, book, req);
}

void
pas_backend_check_connection (PASBackend *backend,
                  PASBook *book,
                  PASCheckConnectionRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->check_connection != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->check_connection) (backend, book, req);
}

void
pas_backend_get_vcard (PASBackend *backend,
               PASBook *book,
               PASGetVCardRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL && req->id != NULL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->get_vcard != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->get_vcard) (backend, book, req);
}

void
pas_backend_get_cursor (PASBackend *backend,
            PASBook *book,
            PASGetCursorRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL && req->search != NULL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->get_cursor != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->get_cursor) (backend, book, req);
}

void
pas_backend_get_book_view (PASBackend *backend,
               PASBook *book,
               PASGetBookViewRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL && req->search != NULL && req->listener != CORBA_OBJECT_NIL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->get_book_view != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->get_book_view) (backend, book, req);
}

void
pas_backend_get_completion_view (PASBackend *backend,
                 PASBook *book,
                 PASGetCompletionViewRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL && req->search != NULL && req->listener != CORBA_OBJECT_NIL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->get_completion_view != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->get_completion_view) (backend, book, req);
}

void
pas_backend_get_changes (PASBackend *backend,
             PASBook *book,
             PASGetChangesRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL && req->change_id != NULL && req->listener != CORBA_OBJECT_NIL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->get_changes != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->get_changes) (backend, book, req);
}

void
pas_backend_authenticate_user (PASBackend *backend,
                   PASBook *book,
                   PASAuthenticateUserRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->authenticate_user != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->authenticate_user) (backend, book, req);
}

void
pas_backend_get_supported_fields (PASBackend *backend,
                  PASBook *book,
                  PASGetSupportedFieldsRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->get_supported_fields != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->get_supported_fields) (backend, book, req);
}

void
pas_backend_get_supported_auth_methods (PASBackend *backend,
                    PASBook *book,
                    PASGetSupportedAuthMethodsRequest *req)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    g_return_if_fail (req != NULL);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->get_supported_auth_methods != NULL);

    (* PAS_BACKEND_GET_CLASS (backend)->get_supported_auth_methods) (backend, book, req);
}

static void
process_client_requests (PASBook *book, gpointer user_data)
{
    PASBackend *backend;
    PASRequest *req;

    backend = PAS_BACKEND (user_data);

    req = pas_book_pop_request (book);
    if (req == NULL)
        return;

    switch (req->op) {
    case CreateCard:
        pas_backend_create_card (backend, book, &req->create);
        break;

    case RemoveCards:
        pas_backend_remove_cards (backend, book, &req->remove);
        break;

    case ModifyCard:
        pas_backend_modify_card (backend, book, &req->modify);
        break;

    case CheckConnection:
        pas_backend_check_connection (backend, book, &req->check_connection);
        break;

    case GetVCard:
        pas_backend_get_vcard (backend, book, &req->get_vcard);
        break;

    case GetCursor:
        pas_backend_get_cursor (backend, book, &req->get_cursor);
        break;

    case GetBookView:
        pas_backend_get_book_view (backend, book, &req->get_book_view);
        break;

    case GetCompletionView:
        pas_backend_get_completion_view (backend, book, &req->get_completion_view);
        break;

    case GetChanges:
        pas_backend_get_changes (backend, book, &req->get_changes);
        break;

    case AuthenticateUser:
        pas_backend_authenticate_user (backend, book, &req->auth_user);
        break;

    case GetSupportedFields:
        pas_backend_get_supported_fields (backend, book, &req->get_supported_fields);
        break;

    case GetSupportedAuthMethods:
        pas_backend_get_supported_auth_methods (backend, book, &req->get_supported_auth_methods);
        break;
    }

    pas_book_free_request (req);
}

static void
book_destroy_cb (gpointer data, GObject *where_book_was)
{
    PASBackend *backend = PAS_BACKEND (data);

    pas_backend_remove_client (backend, (PASBook *)where_book_was);
}

static void
last_client_gone (PASBackend *backend)
{
    g_signal_emit (backend, pas_backend_signals[LAST_CLIENT_GONE], 0);
}

static gboolean
add_client (PASBackend                               *backend,
        GNOME_Evolution_Addressbook_BookListener  listener)
{
    PASBook *book;

    book = pas_book_new (backend, listener);
    if (!book) {
        if (!backend->priv->clients)
            last_client_gone (backend);

        return FALSE;
    }

    g_object_weak_ref (G_OBJECT (book), book_destroy_cb, backend);

    g_signal_connect (book, "requests_queued",
              G_CALLBACK (process_client_requests), backend);

    backend->priv->clients = g_list_prepend (backend->priv->clients, book);

    if (backend->priv->loaded) {
        pas_book_respond_open (
            book, GNOME_Evolution_Addressbook_BookListener_Success);
    } else {
        pas_book_respond_open (
            book, GNOME_Evolution_Addressbook_BookListener_OtherError);
    }

    pas_book_report_writable (book, backend->priv->writable);

    bonobo_object_unref (BONOBO_OBJECT (book));

    return TRUE;
}

/**
 * pas_backend_add_client:
 * @backend: An addressbook backend.
 * @listener: Listener for notification to the client.
 *
 * Adds a client to an addressbook backend.
 *
 * Return value: TRUE on success, FALSE on failure to add the client.
 */
gboolean
pas_backend_add_client (PASBackend                               *backend,
            GNOME_Evolution_Addressbook_BookListener  listener)
{
    g_return_val_if_fail (PAS_IS_BACKEND (backend), FALSE);
    g_return_val_if_fail (listener != CORBA_OBJECT_NIL, FALSE);

    g_assert (PAS_BACKEND_GET_CLASS (backend)->add_client != NULL);

    return PAS_BACKEND_GET_CLASS (backend)->add_client (backend, listener);
}

static void
remove_client (PASBackend *backend,
           PASBook    *book)
{
    /* Disconnect */
    backend->priv->clients = g_list_remove (backend->priv->clients, book);

    /* When all clients go away, notify the parent factory about it so that
     * it may decide whether to kill the backend or not.
     */
    if (!backend->priv->clients)
        last_client_gone (backend);
}

void
pas_backend_remove_client (PASBackend *backend,
               PASBook    *book)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    g_return_if_fail (PAS_IS_BOOK (book));
    
    g_assert (PAS_BACKEND_GET_CLASS (backend)->remove_client != NULL);

    PAS_BACKEND_GET_CLASS (backend)->remove_client (backend, book);
}

char *
pas_backend_get_static_capabilities (PASBackend *backend)
{
    g_return_val_if_fail (backend != NULL, NULL);
    g_return_val_if_fail (PAS_IS_BACKEND (backend), NULL);
    
    g_assert (PAS_BACKEND_GET_CLASS (backend)->get_static_capabilities != NULL);

    return PAS_BACKEND_GET_CLASS (backend)->get_static_capabilities (backend);
}

gboolean
pas_backend_is_loaded (PASBackend *backend)
{
    g_return_val_if_fail (PAS_IS_BACKEND (backend), FALSE);

    return backend->priv->loaded;
}

void
pas_backend_set_is_loaded (PASBackend *backend, gboolean is_loaded)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));

    backend->priv->loaded = is_loaded;
}

gboolean
pas_backend_is_writable (PASBackend *backend)
{
    g_return_val_if_fail (PAS_IS_BACKEND (backend), FALSE);
    
    return backend->priv->writable;
}

void
pas_backend_set_is_writable (PASBackend *backend, gboolean is_writable)
{
    g_return_if_fail (PAS_IS_BACKEND (backend));
    
    backend->priv->writable = is_writable;
}

static void
pas_backend_init (PASBackend *backend)
{
    PASBackendPrivate *priv;

    priv          = g_new0 (PASBackendPrivate, 1);
    priv->clients = NULL;

    backend->priv = priv;
}

static void
pas_backend_dispose (GObject *object)
{
    PASBackend *backend;

    backend = PAS_BACKEND (object);

    if (backend->priv) {
        g_list_free (backend->priv->clients);
        g_free (backend->priv);

        backend->priv = NULL;
    }

    G_OBJECT_CLASS (parent_class)->dispose (object);
}

static void
pas_backend_class_init (PASBackendClass *klass)
{
    GObjectClass *object_class;

    parent_class = g_type_class_peek_parent (klass);

    object_class = (GObjectClass *) klass;

    klass->add_client = add_client;
    klass->remove_client = remove_client;

    object_class->dispose = pas_backend_dispose;

    pas_backend_signals[LAST_CLIENT_GONE] =
        g_signal_new ("last_client_gone",
                  G_OBJECT_CLASS_TYPE (object_class),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (PASBackendClass, last_client_gone),
                  NULL, NULL,
                  pas_marshal_NONE__NONE,
                  G_TYPE_NONE, 0);
}

/**
 * pas_backend_get_type:
 */
GType
pas_backend_get_type (void)
{
    static GType type = 0;

    if (! type) {
        GTypeInfo info = {
            sizeof (PASBackendClass),
            NULL, /* base_class_init */
            NULL, /* base_class_finalize */
            (GClassInitFunc)  pas_backend_class_init,
            NULL, /* class_finalize */
            NULL, /* class_data */
            sizeof (PASBackend),
            0,    /* n_preallocs */
            (GInstanceInitFunc) pas_backend_init
        };

        type = g_type_register_static (G_TYPE_OBJECT, "PASBackend", &info, 0);
    }

    return type;
}