2005-11-07 09:45:58 -06:00
|
|
|
/********************************************************************\
|
|
|
|
* qofobject.c -- the Core Object Registration/Lookup Interface *
|
|
|
|
* This program is free software; you can redistribute it and/or *
|
|
|
|
* modify it under the terms of the GNU General Public License as *
|
|
|
|
* published by the Free Software Foundation; either version 2 of *
|
|
|
|
* the License, or (at your option) any later version. *
|
|
|
|
* *
|
|
|
|
* This program is distributed in the hope that it will be useful, *
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
|
|
|
|
* GNU General Public License for more details. *
|
|
|
|
* *
|
|
|
|
* You should have received a copy of the GNU General Public License*
|
|
|
|
* along with this program; if not, contact: *
|
|
|
|
* *
|
|
|
|
* Free Software Foundation Voice: +1-617-542-5942 *
|
2005-11-16 23:35:02 -06:00
|
|
|
* 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
|
|
|
|
* Boston, MA 02110-1301, USA gnu@gnu.org *
|
2005-11-07 09:45:58 -06:00
|
|
|
* *
|
|
|
|
\********************************************************************/
|
|
|
|
/*
|
|
|
|
* qofobject.c -- the Core Object Object Registry
|
|
|
|
* Copyright (C) 2001 Derek Atkins
|
|
|
|
* Author: Derek Atkins <warlord@MIT.EDU>
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include <glib.h>
|
|
|
|
|
|
|
|
#include "gnc-trace.h"
|
|
|
|
#include "gnc-engine-util.h"
|
|
|
|
#include "qofobject.h"
|
|
|
|
#include "qofobject-p.h"
|
|
|
|
#include "qofbook.h"
|
|
|
|
|
|
|
|
static QofLogModule log_module = QOF_MOD_OBJECT;
|
|
|
|
|
|
|
|
static gboolean object_is_initialized = FALSE;
|
|
|
|
static GList *object_modules = NULL;
|
|
|
|
static GList *book_list = NULL;
|
|
|
|
static GHashTable *backend_data = NULL;
|
|
|
|
|
|
|
|
gpointer
|
|
|
|
qof_object_new_instance (QofIdTypeConst type_name, QofBook *book)
|
|
|
|
{
|
|
|
|
const QofObject *obj;
|
|
|
|
|
|
|
|
if (!type_name) return NULL;
|
|
|
|
|
|
|
|
obj = qof_object_lookup (type_name);
|
|
|
|
if (!obj) return NULL;
|
|
|
|
|
|
|
|
if (obj->create)
|
|
|
|
return (obj->create (book));
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void qof_object_book_begin (QofBook *book)
|
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
if (!book) return;
|
|
|
|
ENTER (" ");
|
|
|
|
for (l = object_modules; l; l = l->next) {
|
|
|
|
QofObject *obj = l->data;
|
|
|
|
if (obj->book_begin)
|
|
|
|
obj->book_begin (book);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remember this book for later */
|
|
|
|
book_list = g_list_prepend (book_list, book);
|
|
|
|
LEAVE (" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
void qof_object_book_end (QofBook *book)
|
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
if (!book) return;
|
|
|
|
ENTER (" ");
|
|
|
|
for (l = object_modules; l; l = l->next) {
|
|
|
|
QofObject *obj = l->data;
|
|
|
|
if (obj->book_end)
|
|
|
|
obj->book_end (book);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Remove it from the list */
|
|
|
|
book_list = g_list_remove (book_list, book);
|
|
|
|
LEAVE (" ");
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
qof_object_is_dirty (QofBook *book)
|
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
if (!book) return FALSE;
|
|
|
|
for (l = object_modules; l; l = l->next)
|
|
|
|
{
|
|
|
|
QofObject *obj = l->data;
|
|
|
|
if (obj->is_dirty)
|
|
|
|
{
|
|
|
|
QofCollection *col;
|
|
|
|
col = qof_book_get_collection (book, obj->e_type);
|
|
|
|
if (obj->is_dirty (col)) return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
qof_object_mark_clean (QofBook *book)
|
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
if (!book) return;
|
|
|
|
for (l = object_modules; l; l = l->next)
|
|
|
|
{
|
|
|
|
QofObject *obj = l->data;
|
|
|
|
if (obj->mark_clean)
|
|
|
|
{
|
|
|
|
QofCollection *col;
|
|
|
|
col = qof_book_get_collection (book, obj->e_type);
|
|
|
|
(obj->mark_clean) (col);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data)
|
|
|
|
{
|
|
|
|
GList *l;
|
|
|
|
|
|
|
|
if (!cb) return;
|
|
|
|
|
|
|
|
for (l = object_modules; l; l = l->next) {
|
|
|
|
QofObject *obj = l->data;
|
|
|
|
(cb) (obj, user_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
|
|
|
|
QofEntityForeachCB cb, gpointer user_data)
|
|
|
|
{
|
|
|
|
QofCollection *col;
|
|
|
|
const QofObject *obj;
|
|
|
|
|
|
|
|
if (!book || !type_name) return;
|
|
|
|
ENTER ("type=%s", type_name);
|
|
|
|
|
|
|
|
obj = qof_object_lookup (type_name);
|
|
|
|
if (!obj)
|
|
|
|
{
|
|
|
|
PERR ("No object of type %s", type_name);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
col = qof_book_get_collection (book, obj->e_type);
|
|
|
|
PINFO ("lookup obj=%p for type=%s", obj, type_name);
|
|
|
|
if (!obj) return;
|
|
|
|
|
|
|
|
PINFO ("type=%s foreach=%p", type_name, obj->foreach);
|
|
|
|
if (obj->foreach)
|
|
|
|
{
|
|
|
|
obj->foreach (col, cb, user_data);
|
|
|
|
}
|
|
|
|
LEAVE ("type=%s", type_name);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *
|
|
|
|
qof_object_printable (QofIdTypeConst type_name, gpointer obj)
|
|
|
|
{
|
|
|
|
const QofObject *b_obj;
|
|
|
|
|
|
|
|
if (!type_name || !obj) return NULL;
|
|
|
|
|
|
|
|
b_obj = qof_object_lookup (type_name);
|
|
|
|
if (!b_obj) return NULL;
|
|
|
|
|
|
|
|
if (b_obj->printable)
|
|
|
|
return (b_obj->printable (obj));
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char * qof_object_get_type_label (QofIdTypeConst type_name)
|
|
|
|
{
|
|
|
|
const QofObject *obj;
|
|
|
|
|
|
|
|
if (!type_name) return NULL;
|
|
|
|
|
|
|
|
obj = qof_object_lookup (type_name);
|
|
|
|
if (!obj) return NULL;
|
|
|
|
|
|
|
|
return (obj->type_label);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean clear_table (gpointer key, gpointer value, gpointer user_data)
|
|
|
|
{
|
|
|
|
g_hash_table_destroy (value);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* INITIALIZATION and PRIVATE FUNCTIONS */
|
|
|
|
|
|
|
|
void qof_object_initialize (void)
|
|
|
|
{
|
|
|
|
if (object_is_initialized) return;
|
|
|
|
backend_data = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
|
object_is_initialized = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void qof_object_shutdown (void)
|
|
|
|
{
|
|
|
|
g_return_if_fail (object_is_initialized == TRUE);
|
|
|
|
|
|
|
|
g_hash_table_foreach_remove (backend_data, clear_table, NULL);
|
|
|
|
g_hash_table_destroy (backend_data);
|
|
|
|
backend_data = NULL;
|
|
|
|
|
|
|
|
g_list_free (object_modules);
|
|
|
|
object_modules = NULL;
|
|
|
|
g_list_free (book_list);
|
|
|
|
book_list = NULL;
|
|
|
|
object_is_initialized = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Register new types of object objects.
|
|
|
|
* Return TRUE if successful,
|
|
|
|
* return FALSE if it fails, invalid arguments, or if the object
|
|
|
|
* already exists
|
|
|
|
*/
|
|
|
|
gboolean qof_object_register (const QofObject *object)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (object_is_initialized, FALSE);
|
|
|
|
|
|
|
|
if (!object) return FALSE;
|
|
|
|
g_return_val_if_fail (object->interface_version == QOF_OBJECT_VERSION, FALSE);
|
|
|
|
|
|
|
|
if (g_list_index (object_modules, (gpointer)object) == -1)
|
|
|
|
object_modules = g_list_prepend (object_modules, (gpointer)object);
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
/* Now initialize all the known books */
|
|
|
|
if (object->book_begin && book_list) {
|
|
|
|
GList *node;
|
|
|
|
for (node = book_list; node; node = node->next)
|
|
|
|
object->book_begin (node->data);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
const QofObject * qof_object_lookup (QofIdTypeConst name)
|
|
|
|
{
|
|
|
|
GList *iter;
|
|
|
|
const QofObject *obj;
|
|
|
|
|
|
|
|
g_return_val_if_fail (object_is_initialized, NULL);
|
|
|
|
|
|
|
|
if (!name) return NULL;
|
|
|
|
|
|
|
|
for (iter = object_modules; iter; iter = iter->next) {
|
|
|
|
obj = iter->data;
|
|
|
|
if (!safe_strcmp (obj->e_type, name))
|
|
|
|
return obj;
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean qof_object_register_backend (QofIdTypeConst type_name,
|
|
|
|
const char *backend_name,
|
|
|
|
gpointer be_data)
|
|
|
|
{
|
|
|
|
GHashTable *ht;
|
|
|
|
g_return_val_if_fail (object_is_initialized, FALSE);
|
|
|
|
|
|
|
|
if (!type_name || *type_name == '\0' ||
|
|
|
|
!backend_name || *backend_name == '\0' ||
|
|
|
|
!be_data)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ht = g_hash_table_lookup (backend_data, backend_name);
|
|
|
|
|
|
|
|
/* If it doesn't already exist, create a new table for this backend */
|
|
|
|
if (!ht) {
|
|
|
|
ht = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
|
g_hash_table_insert (backend_data, (char *)backend_name, ht);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Now insert the data */
|
|
|
|
g_hash_table_insert (ht, (char *)type_name, be_data);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
gpointer qof_object_lookup_backend (QofIdTypeConst type_name,
|
|
|
|
const char *backend_name)
|
|
|
|
{
|
|
|
|
GHashTable *ht;
|
|
|
|
|
|
|
|
if (!type_name || *type_name == '\0' ||
|
|
|
|
!backend_name || *backend_name == '\0')
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
ht = g_hash_table_lookup (backend_data, (char *)backend_name);
|
|
|
|
if (!ht)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return g_hash_table_lookup (ht, (char *)type_name);
|
|
|
|
}
|
|
|
|
|
|
|
|
struct foreach_data {
|
|
|
|
QofForeachBackendTypeCB cb;
|
|
|
|
gpointer user_data;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void foreach_backend (gpointer key, gpointer be_item, gpointer arg)
|
|
|
|
{
|
|
|
|
char *data_type = key;
|
|
|
|
struct foreach_data *cb_data = arg;
|
|
|
|
|
|
|
|
g_return_if_fail (key && be_item && arg);
|
|
|
|
|
|
|
|
/* Call the callback for this data type */
|
|
|
|
(cb_data->cb) (data_type, be_item, cb_data->user_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
void qof_object_foreach_backend (const char *backend_name,
|
|
|
|
QofForeachBackendTypeCB cb,
|
|
|
|
gpointer user_data)
|
|
|
|
{
|
|
|
|
GHashTable *ht;
|
|
|
|
struct foreach_data cb_data;
|
|
|
|
|
|
|
|
if (!backend_name || *backend_name == '\0' || !cb)
|
|
|
|
return;
|
|
|
|
|
|
|
|
ht = g_hash_table_lookup (backend_data, (char *)backend_name);
|
|
|
|
if (!ht)
|
|
|
|
return;
|
|
|
|
|
|
|
|
cb_data.cb = cb;
|
|
|
|
cb_data.user_data = user_data;
|
|
|
|
|
|
|
|
g_hash_table_foreach (ht, foreach_backend, &cb_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* ========================= END OF FILE =================== */
|