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