GnuCash 2.4.99
qif-context.c
00001 /*
00002  * qif-context.c -- create/destroy QIF Contexts
00003  *
00004  * Written By:  Derek Atkins <derek@ihtfp.com>
00005  * Copyright (c) 2003 Derek Atkins <warlord@MIT.EDU>
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License as
00009  * published by the Free Software Foundation; either version 2 of
00010  * the License, or (at your option) any later version.
00011  *
00012  * This program is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, contact:
00019  *
00020  * Free Software Foundation           Voice:  +1-617-542-5942
00021  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652
00022  * Boston, MA  02110-1301,  USA       gnu@gnu.org
00023  */
00024 
00025 #ifdef HAVE_CONFIG_H
00026 #include "config.h"
00027 #endif
00028 
00029 #include <glib.h>
00030 
00031 #include "qif-import-p.h"
00032 #include "qif-objects-p.h"
00033 
00034 static void qif_object_map_get_helper(gpointer key, gpointer value, gpointer listp);
00035 
00036 QifContext
00037 qif_context_new(void)
00038 {
00039     QifContext ctx = g_new0(struct _QifContext, 1);
00040 
00041     ctx->object_lists = g_hash_table_new(g_str_hash, g_str_equal);
00042     ctx->object_maps = g_hash_table_new(g_str_hash, g_str_equal);
00043 
00044     return ctx;
00045 }
00046 
00047 void
00048 qif_context_destroy(QifContext ctx)
00049 {
00050     GList *node, *temp;
00051     QifContext fctx;
00052 
00053     if (!ctx) return;
00054 
00055     /* First, try to destroy all the children contexts */
00056     for (node = ctx->files; node; node = temp)
00057     {
00058         fctx = node->data;
00059         temp = node->next;
00060         qif_context_destroy(fctx);
00061     }
00062 
00063     /* ok, at this point we're actually destroying this context. */
00064 
00065     /* force the end of record */
00066     if (ctx->handler && ctx->handler->end)
00067         ctx->handler->end(ctx);
00068 
00069     /* destroy the state objects */
00070     qif_object_list_destroy(ctx);
00071     qif_object_map_destroy(ctx);
00072 
00073     /* Remove us from our parent context */
00074     if (ctx->parent)
00075         ctx->parent->files = g_list_remove(ctx->parent->files, ctx);
00076 
00077     g_free(ctx->filename);
00078 
00079     g_assert(ctx->files == NULL);
00080     g_free(ctx);
00081 }
00082 
00083 static GList *
00084 qif_context_get_foo_helper(QifContext ctx, GFunc get_helper)
00085 {
00086     GHashTable *ht;
00087     GList *node, *list = NULL;
00088     QifContext fctx;
00089 
00090     g_return_val_if_fail(ctx, NULL);
00091     g_return_val_if_fail(ctx->parsed, NULL);
00092     g_return_val_if_fail(get_helper, NULL);
00093 
00094     ht = g_hash_table_new(g_direct_hash, g_direct_equal);
00095 
00096     for (node = ctx->files; node; node = node->next)
00097     {
00098         fctx = node->data;
00099         qif_object_list_foreach(fctx, QIF_O_TXN, get_helper, ht);
00100     }
00101 
00102     g_hash_table_foreach(ht, qif_object_map_get_helper, &list);
00103     g_hash_table_destroy(ht);
00104 
00105     return list;
00106 }
00107 
00108 static void
00109 qif_get_accts_helper(gpointer obj, gpointer htp)
00110 {
00111     QifTxn txn = obj;
00112     QifSplit split;
00113     GHashTable *ht = htp;
00114     GList *node;
00115 
00116     if (txn->from_acct)
00117         g_hash_table_insert(ht, txn->from_acct, txn->from_acct);
00118 
00119     /* The default_split is using the from_acct, so we can ignore it */
00120 
00121     for (node = txn->splits; node; node = node->next)
00122     {
00123         split = node->data;
00124         if (split->cat.obj && split->cat_is_acct)
00125             g_hash_table_insert(ht, split->cat.acct, split->cat.acct);
00126     }
00127 }
00128 
00129 GList *
00130 qif_context_get_accounts(QifContext ctx)
00131 {
00132     return qif_context_get_foo_helper(ctx, qif_get_accts_helper);
00133 }
00134 
00135 static void
00136 qif_get_cats_helper(gpointer obj, gpointer htp)
00137 {
00138     QifTxn txn = obj;
00139     QifSplit split;
00140     GHashTable *ht = htp;
00141     GList *node;
00142 
00143     /* default_split uses from_acct, so no categories */
00144 
00145     for (node = txn->splits; node; node = node->next)
00146     {
00147         split = node->data;
00148         if (split->cat.obj && !split->cat_is_acct)
00149             g_hash_table_insert(ht, split->cat.cat, split->cat.cat);
00150     }
00151 }
00152 
00153 GList *
00154 qif_context_get_categories(QifContext ctx)
00155 {
00156     return qif_context_get_foo_helper(ctx, qif_get_cats_helper);
00157 }
00158 
00159 /*****************************************************************************/
00160 
00161 /*
00162  * Insert and remove a QifObject from the Object Maps in this Qif Context
00163  */
00164 
00165 gint
00166 qif_object_map_count(QifContext ctx, const char *type)
00167 {
00168     GHashTable *ht;
00169 
00170     g_return_val_if_fail(ctx, 0);
00171     g_return_val_if_fail(ctx->object_maps, 0);
00172     g_return_val_if_fail(type, 0);
00173 
00174     ht = g_hash_table_lookup(ctx->object_maps, type);
00175     if (!ht)
00176         return 0;
00177 
00178     return g_hash_table_size(ht);
00179 }
00180 
00181 void
00182 qif_object_map_foreach(QifContext ctx, const char *type, GHFunc func, gpointer arg)
00183 {
00184     GHashTable *ht;
00185 
00186     g_return_if_fail(ctx);
00187     g_return_if_fail(ctx->object_maps);
00188     g_return_if_fail(type);
00189 
00190     ht = g_hash_table_lookup(ctx->object_maps, type);
00191     if (ht)
00192         g_hash_table_foreach(ht, func, arg);
00193 }
00194 
00195 void
00196 qif_object_map_insert(QifContext ctx, const char *key, QifObject obj)
00197 {
00198     GHashTable *ht;
00199 
00200     g_return_if_fail(ctx);
00201     g_return_if_fail(ctx->object_maps);
00202     g_return_if_fail(key);
00203     g_return_if_fail(obj);
00204     g_return_if_fail(obj->type);
00205 
00206     ht = g_hash_table_lookup(ctx->object_maps, obj->type);
00207     if (!ht)
00208     {
00209         ht = g_hash_table_new(g_str_hash, g_str_equal);
00210         g_assert(ht);
00211         g_hash_table_insert(ctx->object_maps, (gpointer)obj->type, ht);
00212     }
00213 
00214     g_hash_table_insert(ht, (gpointer)key, obj);
00215 }
00216 
00217 void
00218 qif_object_map_remove(QifContext ctx, const char *type, const char *key)
00219 {
00220     GHashTable *ht;
00221 
00222     g_return_if_fail(ctx);
00223     g_return_if_fail(ctx->object_maps);
00224     g_return_if_fail(type);
00225     g_return_if_fail(key);
00226 
00227     ht = g_hash_table_lookup(ctx->object_maps, type);
00228     if (!ht) return;
00229 
00230     g_hash_table_remove(ht, key);
00231 }
00232 
00233 QifObject
00234 qif_object_map_lookup(QifContext ctx, const char *type, const char *key)
00235 {
00236     GHashTable *ht;
00237 
00238     g_return_val_if_fail(ctx, NULL);
00239     g_return_val_if_fail(ctx->object_maps, NULL);
00240     g_return_val_if_fail(type, NULL);
00241     g_return_val_if_fail(key, NULL);
00242 
00243     ht = g_hash_table_lookup(ctx->object_maps, type);
00244     if (!ht) return NULL;
00245 
00246     return g_hash_table_lookup(ht, key);
00247 }
00248 
00249 /* This GList _SHOULD_ be freed by the caller */
00250 
00251 static void
00252 qif_object_map_get_helper(gpointer key, gpointer value, gpointer arg)
00253 {
00254     GList **listp = arg;
00255     g_return_if_fail(listp);
00256 
00257     *listp = g_list_prepend(*listp, value);
00258 }
00259 
00260 GList *
00261 qif_object_map_get(QifContext ctx, const char *type)
00262 {
00263     GHashTable *ht;
00264     GList *list = NULL;
00265 
00266     g_return_val_if_fail(ctx, NULL);
00267     g_return_val_if_fail(ctx->object_maps, NULL);
00268     g_return_val_if_fail(type, NULL);
00269 
00270     ht = g_hash_table_lookup(ctx->object_maps, type);
00271     if (!ht)
00272         return NULL;
00273 
00274     g_hash_table_foreach(ht, qif_object_map_get_helper, &list);
00275 
00276     return list;
00277 }
00278 
00279 static gboolean
00280 qif_object_map_remove_each(gpointer key, gpointer value, gpointer arg)
00281 {
00282     QifObject obj = value;
00283     obj->destroy(obj);
00284     return TRUE;
00285 }
00286 
00287 static gboolean
00288 qif_object_map_remove_all(gpointer key, gpointer value, gpointer arg)
00289 {
00290     GHashTable *ht = value;
00291 
00292     g_hash_table_foreach_remove(ht, qif_object_map_remove_each, NULL);
00293     g_hash_table_destroy(ht);
00294     return TRUE;
00295 }
00296 
00297 void qif_object_map_destroy(QifContext ctx)
00298 {
00299     g_return_if_fail(ctx);
00300     g_return_if_fail(ctx->object_maps);
00301 
00302     g_hash_table_foreach_remove(ctx->object_maps, qif_object_map_remove_all, NULL);
00303     g_hash_table_destroy(ctx->object_maps);
00304 }
00305 
00306 /*****************************************************************************/
00307 
00308 /*
00309  * Insert and remove a QifObject from the Object Lists in this Qif Context
00310  */
00311 
00312 void
00313 qif_object_list_reverse(QifContext ctx, const char *type)
00314 {
00315     GList *list;
00316 
00317     g_return_if_fail(ctx);
00318     g_return_if_fail(ctx->object_lists);
00319     g_return_if_fail(type);
00320 
00321     list = qif_object_list_get(ctx, type);
00322     list = g_list_reverse(list);
00323     g_hash_table_insert(ctx->object_lists, (gpointer)type, list);
00324 }
00325 
00326 gint
00327 qif_object_list_count(QifContext ctx, const char *type)
00328 {
00329     GList *list;
00330 
00331     g_return_val_if_fail(ctx, 0);
00332     g_return_val_if_fail(ctx->object_lists, 0);
00333     g_return_val_if_fail(type, 0);
00334 
00335     list = g_hash_table_lookup(ctx->object_lists, type);
00336     return g_list_length(list);
00337 }
00338 
00339 void
00340 qif_object_list_foreach(QifContext ctx, const char *type, GFunc func, gpointer arg)
00341 {
00342     GList *list;
00343 
00344     g_return_if_fail(ctx);
00345     g_return_if_fail(ctx->object_lists);
00346     g_return_if_fail(type);
00347 
00348     list = qif_object_list_get(ctx, type);
00349     g_list_foreach(list, func, arg);
00350 }
00351 
00352 void
00353 qif_object_list_insert(QifContext ctx, QifObject obj)
00354 {
00355     GList *list;
00356 
00357     g_return_if_fail(ctx);
00358     g_return_if_fail(ctx->object_lists);
00359     g_return_if_fail(obj);
00360     g_return_if_fail(obj->type && *obj->type);
00361 
00362     list = g_hash_table_lookup(ctx->object_lists, obj->type);
00363     list = g_list_prepend(list, obj);
00364     g_hash_table_insert(ctx->object_lists, (gpointer)obj->type, list);
00365 }
00366 
00367 void
00368 qif_object_list_remove(QifContext ctx, QifObject obj)
00369 {
00370     GList *list;
00371 
00372     g_return_if_fail(ctx);
00373     g_return_if_fail(ctx->object_lists);
00374     g_return_if_fail(obj);
00375     g_return_if_fail(obj->type && *obj->type);
00376 
00377     list = g_hash_table_lookup(ctx->object_lists, obj->type);
00378     list = g_list_remove(list, obj);
00379     g_hash_table_insert(ctx->object_lists, (gpointer)obj->type, list);
00380 }
00381 
00382 GList *
00383 qif_object_list_get(QifContext ctx, const char *type)
00384 {
00385     g_return_val_if_fail(ctx, NULL);
00386     g_return_val_if_fail(ctx->object_lists, NULL);
00387     g_return_val_if_fail(type, NULL);
00388 
00389     return g_hash_table_lookup(ctx->object_lists, type);
00390 }
00391 
00392 static gboolean
00393 qif_object_list_remove_all(gpointer key, gpointer value, gpointer arg)
00394 {
00395     GList *list = value;
00396     GList *node;
00397     QifObject obj;
00398 
00399     for (node = list; node; node = node->next)
00400     {
00401         obj = node->data;
00402         obj->destroy(obj);
00403     }
00404 
00405     g_list_free(list);
00406     return TRUE;
00407 }
00408 
00409 void
00410 qif_object_list_destroy(QifContext ctx)
00411 {
00412     g_return_if_fail(ctx);
00413     g_return_if_fail(ctx->object_lists);
00414 
00415     g_hash_table_foreach_remove(ctx->object_lists, qif_object_list_remove_all, NULL);
00416     g_hash_table_destroy(ctx->object_lists);
00417 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines