GnuCash 2.4.99
gnc-book-xml-v2.c
00001 /********************************************************************\
00002  * gnc-book-xml-v2.c -- book xml i/o implementation                 *
00003  *                                                                  *
00004  * Copyright (C) 2001 James LewisMoss <dres@debian.org>             *
00005  * Copyright (C) 2001 Linas Vepstas <linas@linas.org>               *
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 
00026 #include "config.h"
00027 
00028 #include <glib.h>
00029 #include <stdlib.h>
00030 #include <string.h>
00031 
00032 #include "gnc-gconf-utils.h"
00033 #include "gnc-xml-helper.h"
00034 
00035 #include "sixtp.h"
00036 #include "sixtp-utils.h"
00037 #include "sixtp-parsers.h"
00038 #include "sixtp-utils.h"
00039 #include "sixtp-dom-parsers.h"
00040 #include "sixtp-dom-generators.h"
00041 
00042 #include "gnc-xml.h"
00043 #include "io-gncxml-gen.h"
00044 #include "io-gncxml-v2.h"
00045 #include "io-utils.h"
00046 
00047 #include "sixtp-dom-parsers.h"
00048 #include "qof.h"
00049 
00050 /* non-static because it's used in io-gncxml-v2.c */
00051 const gchar *gnc_v2_book_version_string = "2.0.0";
00052 
00053 /* ids */
00054 #define gnc_book_string "gnc:book"
00055 #define book_id_string "book:id"
00056 #define book_slots_string "book:slots"
00057 
00058 static QofLogModule log_module = GNC_MOD_IO;
00059 
00060 /* ================================================================ */
00061 
00062 #ifdef IMPLEMENT_BOOK_DOM_TREES_LATER
00063 
00064 static void
00065 append_account_tree (xmlNodePtr parent,
00066                      Account *account,
00067                      gboolean allow_incompat)
00068 {
00069     GList *children, *node;
00070 
00071     children = gnc_account_get_children(account);
00072     children = g_list_sort(children, qof_instance_guid_compare);
00073     for (node = children; node; node = node->next)
00074     {
00075         xmlNodePtr accnode;
00076         Account *account;
00077 
00078         account = node->data;
00079         accnode = gnc_account_dom_tree_create(account, FALSE, allow_incompat);
00080         xmlAddChild (parent, accnode);
00081         append_account_tree(accnode, account);
00082     }
00083     g_list_free(children);
00084 }
00085 
00086 static int
00087 traverse_txns (Transaction *txn, gpointer data)
00088 {
00089     xmlNodePtr node;
00090     xmlNodePtr parent = data;
00091 
00092     node = gnc_transaction_dom_tree_create(txn);
00093     xmlAddChild (parent, node);
00094 
00095     return 0;
00096 }
00097 #endif
00098 
00099 /* ================================================================ */
00100 
00101 xmlNodePtr
00102 gnc_book_dom_tree_create(QofBook *book)
00103 {
00104     xmlNodePtr ret;
00105     gboolean allow_incompat = TRUE;
00106 
00107     ret = xmlNewNode(NULL, BAD_CAST gnc_book_string);
00108     xmlSetProp(ret, BAD_CAST "version", BAD_CAST gnc_v2_book_version_string);
00109 
00110     xmlAddChild(ret, guid_to_dom_tree(book_id_string,
00111                                       qof_book_get_guid(book)));
00112 
00113     if (qof_book_get_slots(book))
00114     {
00115         xmlNodePtr kvpnode = kvp_frame_to_dom_tree(book_slots_string,
00116                              qof_book_get_slots(book));
00117         if (kvpnode)
00118             xmlAddChild(ret, kvpnode);
00119     }
00120 
00121 #ifdef IMPLEMENT_BOOK_DOM_TREES_LATER
00122     /* theoretically, we should be adding all the below to the book
00123      * but in fact, there's enough brain damage in the code already
00124      * that we are only going to hand-edit the file at a higher layer.
00125      * And that's OK, since its probably a performance boost anyway.
00126      */
00127     xmlAddChild(ret, gnc_commodity_dom_tree_create(
00128                     gnc_commodity_table_get_table(book)));
00129     xmlAddChild(ret, gnc_pricedb_dom_tree_create(gnc_pricedb_get_db(book)));
00130     if (allow_incompat)
00131     {
00132         accnode = gnc_account_dom_tree_create(account, FALSE);
00133         xmlAddChild (ret, rootAccNode);
00134     }
00135     append_account_tree (ret, gnc_book_get_root(book));
00136 
00137     xaccAccountTreeForEachTransaction (gnc_book_get_root_account(book),
00138                                        traverse_txns, ret);
00139 
00140     /* xxx FIXME hack alert how are we going to handle
00141      *  gnc_book_get_template_group handled ???   */
00142     xmlAddChild(ret, gnc_schedXaction_dom_tree_create(
00143                     gnc_book_get_schedxactions(book)));
00144 
00145 #endif
00146 
00147     return ret;
00148 }
00149 
00150 /* ================================================================ */
00151 /* same as above, but we write out directly.  Only handle the guid
00152  * and slots, everything else is handled elsewhere */
00153 
00154 gboolean
00155 write_book_parts(FILE *out, QofBook *book)
00156 {
00157     xmlNodePtr domnode;
00158 
00159     domnode = guid_to_dom_tree(book_id_string, qof_book_get_guid(book));
00160     xmlElemDump(out, NULL, domnode);
00161     xmlFreeNode (domnode);
00162 
00163     if (ferror(out) || fprintf(out, "\n") < 0)
00164         return FALSE;
00165 
00166     if (qof_book_get_slots(book))
00167     {
00168         xmlNodePtr kvpnode = kvp_frame_to_dom_tree(book_slots_string,
00169                              qof_book_get_slots(book));
00170         if (kvpnode)
00171         {
00172             xmlElemDump(out, NULL, kvpnode);
00173             xmlFreeNode(kvpnode);
00174 
00175             if (ferror(out) || fprintf(out, "\n") < 0)
00176                 return FALSE;
00177         }
00178     }
00179 
00180     return TRUE;
00181 }
00182 
00183 
00184 /* ================================================================ */
00185 
00186 static gboolean
00187 book_id_handler(xmlNodePtr node, gpointer book_pdata)
00188 {
00189     QofBook *book = book_pdata;
00190     GncGUID *guid;
00191 
00192     guid = dom_tree_to_guid(node);
00193     qof_instance_set_guid(QOF_INSTANCE(book), guid);
00194     g_free(guid);
00195 
00196     return TRUE;
00197 }
00198 
00199 static gboolean
00200 book_slots_handler (xmlNodePtr node, gpointer book_pdata)
00201 {
00202     QofBook *book = book_pdata;
00203     gboolean success;
00204 
00205     /* the below works only because the get is gaurenteed to return
00206      * a frame, even if its empty */
00207     success = dom_tree_to_kvp_frame_given (node, qof_book_get_slots (book));
00208 
00209     g_return_val_if_fail(success, FALSE);
00210 
00211     return TRUE;
00212 }
00213 
00214 
00215 static struct dom_tree_handler book_handlers_v2[] =
00216 {
00217     { book_id_string, book_id_handler, 1, 0 },
00218     { book_slots_string, book_slots_handler, 0, 0 },
00219     { NULL, 0, 0, 0 }
00220 };
00221 
00222 static gboolean
00223 gnc_book_end_handler(gpointer data_for_children,
00224                      GSList* data_from_children, GSList* sibling_data,
00225                      gpointer parent_data, gpointer global_data,
00226                      gpointer *result, const gchar *tag)
00227 {
00228     int successful;
00229     xmlNodePtr tree = (xmlNodePtr)data_for_children;
00230     gxpf_data *gdata = (gxpf_data*)global_data;
00231     QofBook *book = gdata->bookdata;
00232 
00233     successful = TRUE;
00234 
00235     if (parent_data) return TRUE;
00236 
00237     /* OK.  For some messed up reason this is getting called again with a
00238        NULL tag.  So we ignore those cases */
00239     if (!tag) return TRUE;
00240 
00241     g_return_val_if_fail(tree, FALSE);
00242 
00243     book = dom_tree_to_book(tree, book);
00244     if (!book)
00245         gdata->cb(tag, gdata->parsedata, book);
00246 
00247     xmlFreeNode(tree);
00248 
00249     return book != NULL;
00250 }
00251 
00252 static gboolean
00253 gnc_book_id_end_handler(gpointer data_for_children,
00254                         GSList* data_from_children, GSList* sibling_data,
00255                         gpointer parent_data, gpointer global_data,
00256                         gpointer *result, const gchar *tag)
00257 {
00258     gboolean successful;
00259     xmlNodePtr tree = (xmlNodePtr)data_for_children;
00260     gxpf_data *gdata = (gxpf_data*)global_data;
00261     QofBook *book = gdata->bookdata;
00262 
00263     if (parent_data) return TRUE;
00264     if (!tag) return TRUE;
00265 
00266     g_return_val_if_fail(tree, FALSE);
00267 
00268     successful = book_id_handler(tree, book);
00269     xmlFreeNode(tree);
00270 
00271     return successful;
00272 }
00273 
00274 static gboolean
00275 gnc_book_slots_end_handler(gpointer data_for_children,
00276                            GSList* data_from_children, GSList* sibling_data,
00277                            gpointer parent_data, gpointer global_data,
00278                            gpointer *result, const gchar *tag)
00279 {
00280     gboolean successful;
00281     xmlNodePtr tree = (xmlNodePtr)data_for_children;
00282     gxpf_data *gdata = (gxpf_data*)global_data;
00283     QofBook *book = gdata->bookdata;
00284 
00285     if (parent_data) return TRUE;
00286     if (!tag) return TRUE;
00287 
00288     g_return_val_if_fail(tree, FALSE);
00289 
00290     successful = book_slots_handler (tree, book);
00291     xmlFreeNode(tree);
00292 
00293     return successful;
00294 }
00295 
00296 QofBook*
00297 dom_tree_to_book (xmlNodePtr node, QofBook *book)
00298 {
00299     gboolean successful;
00300 
00301     successful = dom_tree_generic_parse (node, book_handlers_v2,
00302                                          book);
00303     if (!successful)
00304     {
00305         PERR ("failed to parse book");
00306         book = NULL;
00307     }
00308 
00309     return book;
00310 }
00311 
00312 sixtp*
00313 gnc_book_sixtp_parser_create(void)
00314 {
00315     return sixtp_dom_parser_new(gnc_book_end_handler, NULL, NULL);
00316 }
00317 
00318 sixtp*
00319 gnc_book_id_sixtp_parser_create(void)
00320 {
00321     return sixtp_dom_parser_new(gnc_book_id_end_handler, NULL, NULL);
00322 }
00323 
00324 sixtp*
00325 gnc_book_slots_sixtp_parser_create(void)
00326 {
00327     return sixtp_dom_parser_new(gnc_book_slots_end_handler, NULL, NULL);
00328 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines