2005-11-07 09:45:58 -06:00
|
|
|
/********************************************************************\
|
|
|
|
* qofid.c -- QOF entity identifier implementation *
|
|
|
|
* Copyright (C) 2000 Dave Peticolas <dave@krondo.com> *
|
|
|
|
* Copyright (C) 2003 Linas Vepstas <linas@linas.org> *
|
|
|
|
* *
|
|
|
|
* 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
|
|
|
* *
|
|
|
|
\********************************************************************/
|
|
|
|
|
2021-04-20 13:03:23 -05:00
|
|
|
#include <glib.h>
|
|
|
|
|
2017-10-26 04:14:21 -05:00
|
|
|
#include <config.h>
|
2005-11-07 09:45:58 -06:00
|
|
|
#include <string.h>
|
2014-04-25 15:41:11 -05:00
|
|
|
|
2006-01-08 11:51:29 -06:00
|
|
|
#include "qof.h"
|
2005-11-07 09:45:58 -06:00
|
|
|
#include "qofid-p.h"
|
2014-05-07 08:37:14 -05:00
|
|
|
#include "qofinstance-p.h"
|
2005-11-07 09:45:58 -06:00
|
|
|
|
|
|
|
static QofLogModule log_module = QOF_MOD_ENGINE;
|
|
|
|
|
|
|
|
struct QofCollection_s
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
QofIdType e_type;
|
|
|
|
gboolean is_dirty;
|
|
|
|
|
|
|
|
GHashTable * hash_of_entities;
|
|
|
|
gpointer data; /* place where object class can hang arbitrary data */
|
2005-11-07 09:45:58 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
/* =============================================================== */
|
|
|
|
|
|
|
|
QofCollection *
|
|
|
|
qof_collection_new (QofIdType type)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
QofCollection *col;
|
|
|
|
col = g_new0(QofCollection, 1);
|
2014-04-25 15:41:11 -05:00
|
|
|
col->e_type = static_cast<QofIdType>(CACHE_INSERT (type));
|
2009-10-30 15:07:25 -05:00
|
|
|
col->hash_of_entities = guid_hash_table_new();
|
2009-09-18 14:40:57 -05:00
|
|
|
col->data = NULL;
|
|
|
|
return col;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
qof_collection_destroy (QofCollection *col)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
CACHE_REMOVE (col->e_type);
|
|
|
|
g_hash_table_destroy(col->hash_of_entities);
|
|
|
|
col->e_type = NULL;
|
|
|
|
col->hash_of_entities = NULL;
|
|
|
|
col->data = NULL; /** XXX there should be a destroy notifier for this */
|
|
|
|
g_free (col);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* =============================================================== */
|
|
|
|
/* getters */
|
|
|
|
|
|
|
|
QofIdType
|
2006-08-17 23:48:18 -05:00
|
|
|
qof_collection_get_type (const QofCollection *col)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
return col->e_type;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* =============================================================== */
|
|
|
|
|
2007-04-01 17:18:30 -05:00
|
|
|
void
|
2007-04-01 17:18:50 -05:00
|
|
|
qof_collection_remove_entity (QofInstance *ent)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
QofCollection *col;
|
2010-03-27 16:01:21 -05:00
|
|
|
const GncGUID *guid;
|
2009-09-18 14:40:57 -05:00
|
|
|
|
|
|
|
if (!ent) return;
|
|
|
|
col = qof_instance_get_collection(ent);
|
|
|
|
if (!col) return;
|
|
|
|
guid = qof_instance_get_guid(ent);
|
|
|
|
g_hash_table_remove (col->hash_of_entities, guid);
|
|
|
|
qof_instance_set_collection(ent, NULL);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2007-04-01 17:18:50 -05:00
|
|
|
qof_collection_insert_entity (QofCollection *col, QofInstance *ent)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2010-03-27 16:01:21 -05:00
|
|
|
const GncGUID *guid;
|
2009-09-18 14:40:57 -05:00
|
|
|
|
|
|
|
if (!col || !ent) return;
|
|
|
|
guid = qof_instance_get_guid(ent);
|
|
|
|
if (guid_equal(guid, guid_null())) return;
|
|
|
|
g_return_if_fail (col->e_type == ent->e_type);
|
|
|
|
qof_collection_remove_entity (ent);
|
|
|
|
g_hash_table_insert (col->hash_of_entities, (gpointer)guid, ent);
|
|
|
|
qof_instance_set_collection(ent, col);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2007-04-01 17:18:50 -05:00
|
|
|
qof_collection_add_entity (QofCollection *coll, QofInstance *ent)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
QofInstance *e;
|
2010-03-27 16:01:21 -05:00
|
|
|
const GncGUID *guid;
|
2009-09-18 14:40:57 -05:00
|
|
|
|
|
|
|
e = NULL;
|
|
|
|
if (!coll || !ent)
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
guid = qof_instance_get_guid(ent);
|
|
|
|
if (guid_equal(guid, guid_null()))
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
g_return_val_if_fail (coll->e_type == ent->e_type, FALSE);
|
|
|
|
e = qof_collection_lookup_entity(coll, guid);
|
|
|
|
if ( e != NULL )
|
|
|
|
{
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
g_hash_table_insert (coll->hash_of_entities, (gpointer)guid, ent);
|
|
|
|
return TRUE;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
2007-04-01 17:18:50 -05:00
|
|
|
collection_compare_cb (QofInstance *ent, gpointer user_data)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
QofCollection *target;
|
|
|
|
QofInstance *e;
|
2010-03-27 16:01:21 -05:00
|
|
|
const GncGUID *guid;
|
2009-09-18 14:40:57 -05:00
|
|
|
gint value;
|
|
|
|
|
|
|
|
e = NULL;
|
|
|
|
target = (QofCollection*)user_data;
|
|
|
|
if (!target || !ent)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
value = *(gint*)qof_collection_get_data(target);
|
|
|
|
if (value != 0)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
guid = qof_instance_get_guid(ent);
|
|
|
|
if (guid_equal(guid, guid_null()))
|
|
|
|
{
|
|
|
|
value = -1;
|
|
|
|
qof_collection_set_data(target, &value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
g_return_if_fail (target->e_type == ent->e_type);
|
|
|
|
e = qof_collection_lookup_entity(target, guid);
|
|
|
|
if ( e == NULL )
|
|
|
|
{
|
|
|
|
value = 1;
|
|
|
|
qof_collection_set_data(target, &value);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
value = 0;
|
|
|
|
qof_collection_set_data(target, &value);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
gint
|
|
|
|
qof_collection_compare (QofCollection *target, QofCollection *merge)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
gint value;
|
|
|
|
|
|
|
|
value = 0;
|
|
|
|
if (!target && !merge)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (target == merge)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
if (!target && merge)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (target && !merge)
|
|
|
|
{
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
if (target->e_type != merge->e_type)
|
|
|
|
{
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
qof_collection_set_data(target, &value);
|
|
|
|
qof_collection_foreach(merge, collection_compare_cb, target);
|
|
|
|
value = *(gint*)qof_collection_get_data(target);
|
|
|
|
if (value == 0)
|
|
|
|
{
|
|
|
|
qof_collection_set_data(merge, &value);
|
|
|
|
qof_collection_foreach(target, collection_compare_cb, merge);
|
|
|
|
value = *(gint*)qof_collection_get_data(merge);
|
|
|
|
}
|
|
|
|
return value;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2007-04-01 17:18:50 -05:00
|
|
|
QofInstance *
|
2010-03-27 16:01:21 -05:00
|
|
|
qof_collection_lookup_entity (const QofCollection *col, const GncGUID * guid)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
QofInstance *ent;
|
|
|
|
g_return_val_if_fail (col, NULL);
|
|
|
|
if (guid == NULL) return NULL;
|
2014-04-25 15:41:11 -05:00
|
|
|
ent = static_cast<QofInstance*>(g_hash_table_lookup (col->hash_of_entities,
|
|
|
|
guid));
|
2009-09-18 14:40:57 -05:00
|
|
|
return ent;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
QofCollection *
|
2007-12-29 13:40:28 -06:00
|
|
|
qof_collection_from_glist (QofIdType type, const GList *glist)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
QofCollection *coll;
|
|
|
|
QofInstance *ent;
|
|
|
|
const GList *list;
|
|
|
|
|
|
|
|
coll = qof_collection_new(type);
|
|
|
|
for (list = glist; list != NULL; list = list->next)
|
|
|
|
{
|
|
|
|
ent = QOF_INSTANCE(list->data);
|
|
|
|
if (FALSE == qof_collection_add_entity(coll, ent))
|
|
|
|
{
|
2018-11-27 23:48:42 -06:00
|
|
|
qof_collection_destroy(coll);
|
2009-09-18 14:40:57 -05:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return coll;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
guint
|
2006-08-17 23:48:18 -05:00
|
|
|
qof_collection_count (const QofCollection *col)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
guint c;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
c = g_hash_table_size(col->hash_of_entities);
|
|
|
|
return c;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* =============================================================== */
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
gboolean
|
2006-08-17 23:48:18 -05:00
|
|
|
qof_collection_is_dirty (const QofCollection *col)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
return col ? col->is_dirty : FALSE;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
void
|
2005-11-07 09:45:58 -06:00
|
|
|
qof_collection_mark_clean (QofCollection *col)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (col)
|
|
|
|
{
|
|
|
|
col->is_dirty = FALSE;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
void
|
2005-11-07 09:45:58 -06:00
|
|
|
qof_collection_mark_dirty (QofCollection *col)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (col)
|
|
|
|
{
|
|
|
|
col->is_dirty = TRUE;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2006-05-06 01:01:14 -05:00
|
|
|
void
|
2006-08-17 23:48:18 -05:00
|
|
|
qof_collection_print_dirty (const QofCollection *col, gpointer dummy)
|
2006-05-06 01:01:14 -05:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (col->is_dirty)
|
|
|
|
printf("%s collection is dirty.\n", col->e_type);
|
|
|
|
qof_collection_foreach(col, (QofInstanceForeachCB)qof_instance_print_dirty, NULL);
|
2006-05-06 01:01:14 -05:00
|
|
|
}
|
|
|
|
|
2005-11-07 09:45:58 -06:00
|
|
|
/* =============================================================== */
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
gpointer
|
2006-08-17 23:48:18 -05:00
|
|
|
qof_collection_get_data (const QofCollection *col)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
return col ? col->data : NULL;
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
void
|
2005-11-07 09:45:58 -06:00
|
|
|
qof_collection_set_data (QofCollection *col, gpointer user_data)
|
|
|
|
{
|
2009-09-18 14:40:57 -05:00
|
|
|
if (col)
|
|
|
|
{
|
|
|
|
col->data = user_data;
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
/* =============================================================== */
|
|
|
|
|
2020-04-13 21:12:45 -05:00
|
|
|
struct _qofid_iterate
|
2009-09-18 14:40:57 -05:00
|
|
|
{
|
|
|
|
QofInstanceForeachCB fcn;
|
|
|
|
gpointer data;
|
2005-11-07 09:45:58 -06:00
|
|
|
};
|
|
|
|
|
2011-10-14 09:57:54 -05:00
|
|
|
static void
|
|
|
|
foreach_cb (gpointer item, gpointer arg)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2020-04-13 21:12:45 -05:00
|
|
|
struct _qofid_iterate *iter = static_cast<_qofid_iterate*>(arg);
|
2014-04-25 15:41:11 -05:00
|
|
|
QofInstance *ent = static_cast<QofInstance*>(item);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
iter->fcn (ent, iter->data);
|
2005-11-07 09:45:58 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2009-09-18 14:40:57 -05:00
|
|
|
qof_collection_foreach (const QofCollection *col, QofInstanceForeachCB cb_func,
|
2006-01-08 11:51:29 -06:00
|
|
|
gpointer user_data)
|
2005-11-07 09:45:58 -06:00
|
|
|
{
|
2020-04-13 21:12:45 -05:00
|
|
|
struct _qofid_iterate iter;
|
2011-10-14 09:57:54 -05:00
|
|
|
GList *entries;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
g_return_if_fail (col);
|
|
|
|
g_return_if_fail (cb_func);
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2009-09-18 14:40:57 -05:00
|
|
|
iter.fcn = cb_func;
|
|
|
|
iter.data = user_data;
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2011-10-14 09:57:54 -05:00
|
|
|
PINFO("Hash Table size of %s before is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
|
2005-11-07 09:45:58 -06:00
|
|
|
|
2011-10-14 09:57:54 -05:00
|
|
|
entries = g_hash_table_get_values (col->hash_of_entities);
|
|
|
|
g_list_foreach (entries, foreach_cb, &iter);
|
|
|
|
g_list_free (entries);
|
|
|
|
|
|
|
|
PINFO("Hash Table size of %s after is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
|
|
|
|
}
|
2005-11-07 09:45:58 -06:00
|
|
|
/* =============================================================== */
|