GnuCash 2.4.99
qofid.c
00001 /********************************************************************\
00002  * qofid.c -- QOF entity identifier implementation                  *
00003  * Copyright (C) 2000 Dave Peticolas <dave@krondo.com>              *
00004  * Copyright (C) 2003 Linas Vepstas <linas@linas.org>               *
00005  *                                                                  *
00006  * This program is free software; you can redistribute it and/or    *
00007  * modify it under the terms of the GNU General Public License as   *
00008  * published by the Free Software Foundation; either version 2 of   *
00009  * the License, or (at your option) any later version.              *
00010  *                                                                  *
00011  * This program is distributed in the hope that it will be useful,  *
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00014  * GNU General Public License for more details.                     *
00015  *                                                                  *
00016  * You should have received a copy of the GNU General Public License*
00017  * along with this program; if not, contact:                        *
00018  *                                                                  *
00019  * Free Software Foundation           Voice:  +1-617-542-5942       *
00020  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00021  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00022  *                                                                  *
00023 \********************************************************************/
00024 
00025 #include "config.h"
00026 
00027 #include <string.h>
00028 #include <glib.h>
00029 
00030 #include "qof.h"
00031 #include "qofid-p.h"
00032 
00033 static QofLogModule log_module = QOF_MOD_ENGINE;
00034 static gboolean qof_alt_dirty_mode = FALSE;
00035 
00036 struct QofCollection_s
00037 {
00038     QofIdType    e_type;
00039     gboolean     is_dirty;
00040 
00041     GHashTable * hash_of_entities;
00042     gpointer     data;       /* place where object class can hang arbitrary data */
00043 };
00044 
00045 /* =============================================================== */
00046 
00047 gboolean
00048 qof_get_alt_dirty_mode (void)
00049 {
00050     return qof_alt_dirty_mode;
00051 }
00052 
00053 void
00054 qof_set_alt_dirty_mode (gboolean enabled)
00055 {
00056     qof_alt_dirty_mode = enabled;
00057 }
00058 
00059 /* =============================================================== */
00060 
00061 QofCollection *
00062 qof_collection_new (QofIdType type)
00063 {
00064     QofCollection *col;
00065     col = g_new0(QofCollection, 1);
00066     col->e_type = CACHE_INSERT (type);
00067     col->hash_of_entities = guid_hash_table_new();
00068     col->data = NULL;
00069     return col;
00070 }
00071 
00072 void
00073 qof_collection_destroy (QofCollection *col)
00074 {
00075     CACHE_REMOVE (col->e_type);
00076     g_hash_table_destroy(col->hash_of_entities);
00077     col->e_type = NULL;
00078     col->hash_of_entities = NULL;
00079     col->data = NULL;   
00080     g_free (col);
00081 }
00082 
00083 /* =============================================================== */
00084 /* getters */
00085 
00086 QofIdType
00087 qof_collection_get_type (const QofCollection *col)
00088 {
00089     return col->e_type;
00090 }
00091 
00092 /* =============================================================== */
00093 
00094 void
00095 qof_collection_remove_entity (QofInstance *ent)
00096 {
00097     QofCollection *col;
00098     const GncGUID *guid;
00099 
00100     if (!ent) return;
00101     col = qof_instance_get_collection(ent);
00102     if (!col) return;
00103     guid = qof_instance_get_guid(ent);
00104     g_hash_table_remove (col->hash_of_entities, guid);
00105     if (!qof_alt_dirty_mode)
00106         qof_collection_mark_dirty(col);
00107     qof_instance_set_collection(ent, NULL);
00108 }
00109 
00110 void
00111 qof_collection_insert_entity (QofCollection *col, QofInstance *ent)
00112 {
00113     const GncGUID *guid;
00114 
00115     if (!col || !ent) return;
00116     guid = qof_instance_get_guid(ent);
00117     if (guid_equal(guid, guid_null())) return;
00118     g_return_if_fail (col->e_type == ent->e_type);
00119     qof_collection_remove_entity (ent);
00120     g_hash_table_insert (col->hash_of_entities, (gpointer)guid, ent);
00121     if (!qof_alt_dirty_mode)
00122         qof_collection_mark_dirty(col);
00123     qof_instance_set_collection(ent, col);
00124 }
00125 
00126 gboolean
00127 qof_collection_add_entity (QofCollection *coll, QofInstance *ent)
00128 {
00129     QofInstance *e;
00130     const GncGUID *guid;
00131 
00132     e = NULL;
00133     if (!coll || !ent)
00134     {
00135         return FALSE;
00136     }
00137     guid = qof_instance_get_guid(ent);
00138     if (guid_equal(guid, guid_null()))
00139     {
00140         return FALSE;
00141     }
00142     g_return_val_if_fail (coll->e_type == ent->e_type, FALSE);
00143     e = qof_collection_lookup_entity(coll, guid);
00144     if ( e != NULL )
00145     {
00146         return FALSE;
00147     }
00148     g_hash_table_insert (coll->hash_of_entities, (gpointer)guid, ent);
00149     if (!qof_alt_dirty_mode)
00150         qof_collection_mark_dirty(coll);
00151     return TRUE;
00152 }
00153 
00154 
00155 static void
00156 collection_compare_cb (QofInstance *ent, gpointer user_data)
00157 {
00158     QofCollection *target;
00159     QofInstance *e;
00160     const GncGUID *guid;
00161     gint value;
00162 
00163     e = NULL;
00164     target = (QofCollection*)user_data;
00165     if (!target || !ent)
00166     {
00167         return;
00168     }
00169     value = *(gint*)qof_collection_get_data(target);
00170     if (value != 0)
00171     {
00172         return;
00173     }
00174     guid = qof_instance_get_guid(ent);
00175     if (guid_equal(guid, guid_null()))
00176     {
00177         value = -1;
00178         qof_collection_set_data(target, &value);
00179         return;
00180     }
00181     g_return_if_fail (target->e_type == ent->e_type);
00182     e = qof_collection_lookup_entity(target, guid);
00183     if ( e == NULL )
00184     {
00185         value = 1;
00186         qof_collection_set_data(target, &value);
00187         return;
00188     }
00189     value = 0;
00190     qof_collection_set_data(target, &value);
00191 }
00192 
00193 gint
00194 qof_collection_compare (QofCollection *target, QofCollection *merge)
00195 {
00196     gint value;
00197 
00198     value = 0;
00199     if (!target && !merge)
00200     {
00201         return 0;
00202     }
00203     if (target == merge)
00204     {
00205         return 0;
00206     }
00207     if (!target && merge)
00208     {
00209         return -1;
00210     }
00211     if (target && !merge)
00212     {
00213         return 1;
00214     }
00215     if (target->e_type != merge->e_type)
00216     {
00217         return -1;
00218     }
00219     qof_collection_set_data(target, &value);
00220     qof_collection_foreach(merge, collection_compare_cb, target);
00221     value = *(gint*)qof_collection_get_data(target);
00222     if (value == 0)
00223     {
00224         qof_collection_set_data(merge, &value);
00225         qof_collection_foreach(target, collection_compare_cb, merge);
00226         value = *(gint*)qof_collection_get_data(merge);
00227     }
00228     return value;
00229 }
00230 
00231 QofInstance *
00232 qof_collection_lookup_entity (const QofCollection *col, const GncGUID * guid)
00233 {
00234     QofInstance *ent;
00235     g_return_val_if_fail (col, NULL);
00236     if (guid == NULL) return NULL;
00237     ent = g_hash_table_lookup (col->hash_of_entities, guid);
00238     return ent;
00239 }
00240 
00241 QofCollection *
00242 qof_collection_from_glist (QofIdType type, const GList *glist)
00243 {
00244     QofCollection *coll;
00245     QofInstance *ent;
00246     const GList *list;
00247 
00248     coll = qof_collection_new(type);
00249     for (list = glist; list != NULL; list = list->next)
00250     {
00251         ent = QOF_INSTANCE(list->data);
00252         if (FALSE == qof_collection_add_entity(coll, ent))
00253         {
00254             return NULL;
00255         }
00256     }
00257     return coll;
00258 }
00259 
00260 guint
00261 qof_collection_count (const QofCollection *col)
00262 {
00263     guint c;
00264 
00265     c = g_hash_table_size(col->hash_of_entities);
00266     return c;
00267 }
00268 
00269 /* =============================================================== */
00270 
00271 gboolean
00272 qof_collection_is_dirty (const QofCollection *col)
00273 {
00274     return col ? col->is_dirty : FALSE;
00275 }
00276 
00277 void
00278 qof_collection_mark_clean (QofCollection *col)
00279 {
00280     if (col)
00281     {
00282         col->is_dirty = FALSE;
00283     }
00284 }
00285 
00286 void
00287 qof_collection_mark_dirty (QofCollection *col)
00288 {
00289     if (col)
00290     {
00291         col->is_dirty = TRUE;
00292     }
00293 }
00294 
00295 void
00296 qof_collection_print_dirty (const QofCollection *col, gpointer dummy)
00297 {
00298     if (col->is_dirty)
00299         printf("%s collection is dirty.\n", col->e_type);
00300     qof_collection_foreach(col, (QofInstanceForeachCB)qof_instance_print_dirty, NULL);
00301 }
00302 
00303 /* =============================================================== */
00304 
00305 gpointer
00306 qof_collection_get_data (const QofCollection *col)
00307 {
00308     return col ? col->data : NULL;
00309 }
00310 
00311 void
00312 qof_collection_set_data (QofCollection *col, gpointer user_data)
00313 {
00314     if (col)
00315     {
00316         col->data = user_data;
00317     }
00318 }
00319 
00320 /* =============================================================== */
00321 
00322 struct _iterate
00323 {
00324     QofInstanceForeachCB      fcn;
00325     gpointer                data;
00326 };
00327 
00328 static void
00329 foreach_cb (gpointer item, gpointer arg)
00330 {
00331     struct _iterate *iter = arg;
00332     QofInstance *ent = item;
00333 
00334     iter->fcn (ent, iter->data);
00335 }
00336 
00337 void
00338 qof_collection_foreach (const QofCollection *col, QofInstanceForeachCB cb_func,
00339                         gpointer user_data)
00340 {
00341     struct _iterate iter;
00342     GList *entries;
00343 
00344     g_return_if_fail (col);
00345     g_return_if_fail (cb_func);
00346 
00347     iter.fcn = cb_func;
00348     iter.data = user_data;
00349 
00350     PINFO("Hash Table size of %s before is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
00351 
00352     entries = g_hash_table_get_values (col->hash_of_entities);
00353     g_list_foreach (entries, foreach_cb, &iter);
00354     g_list_free (entries);
00355 
00356     PINFO("Hash Table size of %s after is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
00357 }
00358 /* =============================================================== */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines