GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-book-xml-v2.c
1 /********************************************************************\
2  * gnc-book-xml-v2.c -- book xml i/o implementation *
3  * *
4  * Copyright (C) 2001 James LewisMoss <[email protected]> *
5  * Copyright (C) 2001 Linas Vepstas <[email protected]> *
6  * *
7  * This program is free software; you can redistribute it and/or *
8  * modify it under the terms of the GNU General Public License as *
9  * published by the Free Software Foundation; either version 2 of *
10  * the License, or (at your option) any later version. *
11  * *
12  * This program is distributed in the hope that it will be useful, *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15  * GNU General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU General Public License*
18  * along with this program; if not, contact: *
19  * *
20  * Free Software Foundation Voice: +1-617-542-5942 *
21  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
22  * Boston, MA 02110-1301, USA [email protected] *
23  * *
24 \********************************************************************/
25 
26 #include "config.h"
27 
28 #include <glib.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "gnc-xml-helper.h"
33 
34 #include "sixtp.h"
35 #include "sixtp-utils.h"
36 #include "sixtp-parsers.h"
37 #include "sixtp-utils.h"
38 #include "sixtp-dom-parsers.h"
39 #include "sixtp-dom-generators.h"
40 
41 #include "gnc-xml.h"
42 #include "io-gncxml-gen.h"
43 #include "io-gncxml-v2.h"
44 #include "io-utils.h"
45 
46 #include "sixtp-dom-parsers.h"
47 #include "qof.h"
48 
49 /* non-static because it's used in io-gncxml-v2.c */
50 const gchar *gnc_v2_book_version_string = "2.0.0";
51 
52 /* ids */
53 #define gnc_book_string "gnc:book"
54 #define book_id_string "book:id"
55 #define book_slots_string "book:slots"
56 
57 static QofLogModule log_module = GNC_MOD_IO;
58 
59 /* ================================================================ */
60 
61 #ifdef IMPLEMENT_BOOK_DOM_TREES_LATER
62 
63 static void
64 append_account_tree (xmlNodePtr parent,
65  Account *account,
66  gboolean allow_incompat)
67 {
68  GList *children, *node;
69 
70  children = gnc_account_get_children(account);
71  children = g_list_sort(children, qof_instance_guid_compare);
72  for (node = children; node; node = node->next)
73  {
74  xmlNodePtr accnode;
75  Account *account;
76 
77  account = node->data;
78  accnode = gnc_account_dom_tree_create(account, FALSE, allow_incompat);
79  xmlAddChild (parent, accnode);
80  append_account_tree(accnode, account);
81  }
82  g_list_free(children);
83 }
84 
85 static int
86 traverse_txns (Transaction *txn, gpointer data)
87 {
88  xmlNodePtr node;
89  xmlNodePtr parent = data;
90 
91  node = gnc_transaction_dom_tree_create(txn);
92  xmlAddChild (parent, node);
93 
94  return 0;
95 }
96 #endif
97 
98 /* ================================================================ */
99 
100 xmlNodePtr
101 gnc_book_dom_tree_create(QofBook *book)
102 {
103  xmlNodePtr ret;
104  G_GNUC_UNUSED gboolean allow_incompat = TRUE;
105 
106  ret = xmlNewNode(NULL, BAD_CAST gnc_book_string);
107  xmlSetProp(ret, BAD_CAST "version", BAD_CAST gnc_v2_book_version_string);
108 
109  xmlAddChild(ret, guid_to_dom_tree(book_id_string,
110  qof_book_get_guid(book)));
111 
112  if (qof_instance_get_slots (QOF_INSTANCE (book)))
113  {
114  xmlNodePtr kvpnode = kvp_frame_to_dom_tree(book_slots_string,
115  qof_instance_get_slots (QOF_INSTANCE (book)));
116  if (kvpnode)
117  xmlAddChild(ret, kvpnode);
118  }
119 
120 #ifdef IMPLEMENT_BOOK_DOM_TREES_LATER
121  /* theoretically, we should be adding all the below to the book
122  * but in fact, there's enough brain damage in the code already
123  * that we are only going to hand-edit the file at a higher layer.
124  * And that's OK, since its probably a performance boost anyway.
125  */
126  xmlAddChild(ret, gnc_commodity_dom_tree_create(
128  xmlAddChild(ret, gnc_pricedb_dom_tree_create(gnc_pricedb_get_db(book)));
129  if (allow_incompat)
130  {
131  accnode = gnc_account_dom_tree_create(account, FALSE);
132  xmlAddChild (ret, rootAccNode);
133  }
134  append_account_tree (ret, gnc_book_get_root(book));
135 
136  xaccAccountTreeForEachTransaction (gnc_book_get_root_account(book),
137  traverse_txns, ret);
138 
139  /* xxx FIXME hack alert how are we going to handle
140  * gnc_book_get_template_group handled ??? */
141  xmlAddChild(ret, gnc_schedXaction_dom_tree_create(
142  gnc_book_get_schedxactions(book)));
143 
144 #endif
145 
146  return ret;
147 }
148 
149 /* ================================================================ */
150 /* same as above, but we write out directly. Only handle the guid
151  * and slots, everything else is handled elsewhere */
152 
153 gboolean
154 write_book_parts(FILE *out, QofBook *book)
155 {
156  xmlNodePtr domnode;
157 
158  domnode = guid_to_dom_tree(book_id_string, qof_book_get_guid(book));
159  xmlElemDump(out, NULL, domnode);
160  xmlFreeNode (domnode);
161 
162  if (ferror(out) || fprintf(out, "\n") < 0)
163  return FALSE;
164 
165  if (qof_instance_get_slots (QOF_INSTANCE (book)))
166  {
167  xmlNodePtr kvpnode = kvp_frame_to_dom_tree(book_slots_string,
168  qof_instance_get_slots (QOF_INSTANCE (book)));
169  if (kvpnode)
170  {
171  xmlElemDump(out, NULL, kvpnode);
172  xmlFreeNode(kvpnode);
173 
174  if (ferror(out) || fprintf(out, "\n") < 0)
175  return FALSE;
176  }
177  }
178 
179  return TRUE;
180 }
181 
182 
183 /* ================================================================ */
184 
185 static gboolean
186 book_id_handler(xmlNodePtr node, gpointer book_pdata)
187 {
188  QofBook *book = book_pdata;
189  GncGUID *guid;
190 
191  guid = dom_tree_to_guid(node);
192  qof_instance_set_guid(QOF_INSTANCE(book), guid);
193  g_free(guid);
194 
195  return TRUE;
196 }
197 
198 static gboolean
199 book_slots_handler (xmlNodePtr node, gpointer book_pdata)
200 {
201  QofBook *book = book_pdata;
202  gboolean success;
203 
204  /* the below works only because the get is gaurenteed to return
205  * a frame, even if its empty */
206  success = dom_tree_to_kvp_frame_given (node, qof_instance_get_slots (QOF_INSTANCE (book)));
207 
208  g_return_val_if_fail(success, FALSE);
209 
210  return TRUE;
211 }
212 
213 
214 static struct dom_tree_handler book_handlers_v2[] =
215 {
216  { book_id_string, book_id_handler, 1, 0 },
217  { book_slots_string, book_slots_handler, 0, 0 },
218  { NULL, 0, 0, 0 }
219 };
220 
221 static gboolean
222 gnc_book_end_handler(gpointer data_for_children,
223  GSList* data_from_children, GSList* sibling_data,
224  gpointer parent_data, gpointer global_data,
225  gpointer *result, const gchar *tag)
226 {
227  xmlNodePtr tree = (xmlNodePtr)data_for_children;
228  gxpf_data *gdata = (gxpf_data*)global_data;
229  QofBook *book = gdata->bookdata;
230 
231 
232  if (parent_data) return TRUE;
233 
234  /* OK. For some messed up reason this is getting called again with a
235  NULL tag. So we ignore those cases */
236  if (!tag) return TRUE;
237 
238  g_return_val_if_fail(tree, FALSE);
239 
240  book = dom_tree_to_book(tree, book);
241  if (!book)
242  gdata->cb(tag, gdata->parsedata, book);
243 
244  xmlFreeNode(tree);
245 
246  return book != NULL;
247 }
248 
249 static gboolean
250 gnc_book_id_end_handler(gpointer data_for_children,
251  GSList* data_from_children, GSList* sibling_data,
252  gpointer parent_data, gpointer global_data,
253  gpointer *result, const gchar *tag)
254 {
255  gboolean successful;
256  xmlNodePtr tree = (xmlNodePtr)data_for_children;
257  gxpf_data *gdata = (gxpf_data*)global_data;
258  QofBook *book = gdata->bookdata;
259 
260  if (parent_data) return TRUE;
261  if (!tag) return TRUE;
262 
263  g_return_val_if_fail(tree, FALSE);
264 
265  successful = book_id_handler(tree, book);
266  xmlFreeNode(tree);
267 
268  return successful;
269 }
270 
271 static gboolean
272 gnc_book_slots_end_handler(gpointer data_for_children,
273  GSList* data_from_children, GSList* sibling_data,
274  gpointer parent_data, gpointer global_data,
275  gpointer *result, const gchar *tag)
276 {
277  gboolean successful;
278  xmlNodePtr tree = (xmlNodePtr)data_for_children;
279  gxpf_data *gdata = (gxpf_data*)global_data;
280  QofBook *book = gdata->bookdata;
281 
282  if (parent_data) return TRUE;
283  if (!tag) return TRUE;
284 
285  g_return_val_if_fail(tree, FALSE);
286 
287  successful = book_slots_handler (tree, book);
288  xmlFreeNode(tree);
289 
290  return successful;
291 }
292 
293 QofBook*
294 dom_tree_to_book (xmlNodePtr node, QofBook *book)
295 {
296  gboolean successful;
297 
298  successful = dom_tree_generic_parse (node, book_handlers_v2,
299  book);
300  if (!successful)
301  {
302  PERR ("failed to parse book");
303  book = NULL;
304  }
305 
306  return book;
307 }
308 
309 sixtp*
310 gnc_book_sixtp_parser_create(void)
311 {
312  return sixtp_dom_parser_new(gnc_book_end_handler, NULL, NULL);
313 }
314 
315 sixtp*
316 gnc_book_id_sixtp_parser_create(void)
317 {
318  return sixtp_dom_parser_new(gnc_book_id_end_handler, NULL, NULL);
319 }
320 
321 sixtp*
322 gnc_book_slots_sixtp_parser_create(void)
323 {
324  return sixtp_dom_parser_new(gnc_book_slots_end_handler, NULL, NULL);
325 }
int xaccAccountTreeForEachTransaction(Account *acc, TransactionCallback proc, void *data)
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Definition: sixtp.h:93
#define PERR(format, args...)
Definition: qoflog.h:237
GNCPriceDB * gnc_pricedb_get_db(QofBook *book)
Definition: gnc-pricedb.c:872
Definition: guid.h:65
api for GnuCash version 2 XML-based file format
#define qof_book_get_guid(X)
Definition: qofbook.h:351
GList * gnc_account_get_children(const Account *account)
Definition: Account.c:2654
gint qof_instance_guid_compare(const gconstpointer ptr1, const gconstpointer ptr2)
const gchar * QofLogModule
Definition: qofid.h:89