|
GnuCash 2.4.99
|
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 }
1.7.4