GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-vendor-xml-v2.c
1 /********************************************************************\
2  * gnc-vendor-xml-v2.c -- vendor xml i/o implementation *
3  * *
4  * Copyright (C) 2002 Derek Atkins <[email protected]> *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU General Public License as *
8  * published by the Free Software Foundation; either version 2 of *
9  * the License, or (at your option) any later version. *
10  * *
11  * This program is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License*
17  * along with this program; if not, contact: *
18  * *
19  * Free Software Foundation Voice: +1-617-542-5942 *
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21  * Boston, MA 02110-1301, USA [email protected] *
22  * *
23 \********************************************************************/
24 
25 #include "config.h"
26 
27 #include <glib.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #include "gnc-xml-helper.h"
32 
33 #include "sixtp.h"
34 #include "sixtp-utils.h"
35 #include "sixtp-parsers.h"
36 #include "sixtp-utils.h"
37 #include "sixtp-dom-parsers.h"
38 #include "sixtp-dom-generators.h"
39 
40 #include "gnc-xml.h"
41 #include "io-gncxml-gen.h"
42 #include "io-gncxml-v2.h"
43 
44 #include "gncBillTermP.h"
45 #include "gncVendorP.h"
46 #include "gncTaxTableP.h"
47 #include "gnc-vendor-xml-v2.h"
48 #include "gnc-address-xml-v2.h"
49 #include "xml-helpers.h"
50 #include "gnc-bill-term-xml-v2.h"
51 
52 #define _GNC_MOD_NAME GNC_ID_VENDOR
53 
54 static QofLogModule log_module = GNC_MOD_IO;
55 
56 const gchar *vendor_version_string = "2.0.0";
57 
58 /* ids */
59 #define gnc_vendor_string "gnc:GncVendor"
60 #define vendor_name_string "vendor:name"
61 #define vendor_guid_string "vendor:guid"
62 #define vendor_id_string "vendor:id"
63 #define vendor_addr_string "vendor:addr"
64 #define vendor_notes_string "vendor:notes"
65 #define vendor_terms_string "vendor:terms"
66 #define vendor_taxincluded_string "vendor:taxincluded"
67 #define vendor_active_string "vendor:active"
68 #define vendor_currency_string "vendor:currency"
69 #define vendor_taxtable_string "vendor:taxtable"
70 #define vendor_taxtableoverride_string "vendor:use-tt"
71 #define vendor_slots_string "vendor:slots"
72 
73 static xmlNodePtr
74 vendor_dom_tree_create (GncVendor *vendor)
75 {
76  xmlNodePtr ret, kvpnode;
77  GncBillTerm *term;
78  GncTaxTable *taxtable;
79 
80  ret = xmlNewNode(NULL, BAD_CAST gnc_vendor_string);
81  xmlSetProp(ret, BAD_CAST "version", BAD_CAST vendor_version_string);
82 
83  xmlAddChild(ret, guid_to_dom_tree(vendor_guid_string,
84  qof_instance_get_guid (QOF_INSTANCE(vendor))));
85 
86  xmlAddChild(ret, text_to_dom_tree(vendor_name_string,
87  gncVendorGetName (vendor)));
88 
89  xmlAddChild(ret, text_to_dom_tree(vendor_id_string,
90  gncVendorGetID (vendor)));
91 
92  xmlAddChild(ret, gnc_address_to_dom_tree(vendor_addr_string,
93  gncVendorGetAddr (vendor)));
94 
95  maybe_add_string (ret, vendor_notes_string, gncVendorGetNotes (vendor));
96 
97  term = gncVendorGetTerms (vendor);
98  if (term)
99  xmlAddChild(ret, guid_to_dom_tree(vendor_terms_string,
100  qof_instance_get_guid(QOF_INSTANCE(term))));
101 
102  xmlAddChild(ret, text_to_dom_tree(vendor_taxincluded_string,
103  gncTaxIncludedTypeToString (
104  gncVendorGetTaxIncluded (vendor))));
105 
106  xmlAddChild(ret, int_to_dom_tree(vendor_active_string,
107  gncVendorGetActive (vendor)));
108 
109  xmlAddChild
110  (ret,
111  commodity_ref_to_dom_tree(vendor_currency_string,
112  gncVendorGetCurrency (vendor)));
113 
114  xmlAddChild (ret, int_to_dom_tree (vendor_taxtableoverride_string,
115  gncVendorGetTaxTableOverride (vendor)));
116  taxtable = gncVendorGetTaxTable (vendor);
117  if (taxtable)
118  xmlAddChild (ret, guid_to_dom_tree (vendor_taxtable_string,
119  qof_instance_get_guid(QOF_INSTANCE(taxtable))));
120 
121  kvpnode = kvp_frame_to_dom_tree (vendor_slots_string,
122  qof_instance_get_slots (QOF_INSTANCE(vendor)));
123  if (kvpnode) xmlAddChild (ret, kvpnode);
124 
125  return ret;
126 }
127 
128 /***********************************************************************/
129 
131 {
132  GncVendor *vendor;
133  QofBook *book;
134 };
135 
136 static gboolean
137 set_string(xmlNodePtr node, GncVendor* vendor,
138  void (*func)(GncVendor *vendor, const char *txt))
139 {
140  char* txt = dom_tree_to_text(node);
141  g_return_val_if_fail(txt, FALSE);
142 
143  func(vendor, txt);
144 
145  g_free(txt);
146 
147  return TRUE;
148 }
149 
150 static gboolean
151 set_boolean(xmlNodePtr node, GncVendor* vendor,
152  void (*func)(GncVendor* vendor, gboolean b))
153 {
154  gint64 val;
155  gboolean ret;
156 
157  ret = dom_tree_to_integer(node, &val);
158  if (ret)
159  func(vendor, (gboolean)val);
160 
161  return ret;
162 }
163 
164 static gboolean
165 vendor_name_handler (xmlNodePtr node, gpointer vendor_pdata)
166 {
167  struct vendor_pdata *pdata = vendor_pdata;
168 
169  return set_string(node, pdata->vendor, gncVendorSetName);
170 }
171 
172 static gboolean
173 vendor_guid_handler (xmlNodePtr node, gpointer vendor_pdata)
174 {
175  struct vendor_pdata *pdata = vendor_pdata;
176  GncGUID *guid;
177  GncVendor *vendor;
178 
179  guid = dom_tree_to_guid(node);
180  g_return_val_if_fail(guid, FALSE);
181  vendor = gncVendorLookup (pdata->book, guid);
182  if (vendor)
183  {
184  gncVendorDestroy (pdata->vendor);
185  pdata->vendor = vendor;
186  gncVendorBeginEdit (vendor);
187  }
188  else
189  {
190  gncVendorSetGUID(pdata->vendor, guid);
191  }
192 
193  g_free(guid);
194 
195  return TRUE;
196 }
197 
198 static gboolean
199 vendor_id_handler (xmlNodePtr node, gpointer vendor_pdata)
200 {
201  struct vendor_pdata *pdata = vendor_pdata;
202 
203  return set_string(node, pdata->vendor, gncVendorSetID);
204 }
205 
206 static gboolean
207 vendor_notes_handler (xmlNodePtr node, gpointer vendor_pdata)
208 {
209  struct vendor_pdata *pdata = vendor_pdata;
210 
211  return set_string(node, pdata->vendor, gncVendorSetNotes);
212 }
213 
214 static gboolean
215 vendor_terms_handler (xmlNodePtr node, gpointer vendor_pdata)
216 {
217  struct vendor_pdata *pdata = vendor_pdata;
218  GncGUID *guid;
219  GncBillTerm *term;
220 
221  guid = dom_tree_to_guid(node);
222  g_return_val_if_fail (guid, FALSE);
223  term = gnc_billterm_xml_find_or_create(pdata->book, guid);
224  g_assert(term);
225  g_free (guid);
226  gncVendorSetTerms (pdata->vendor, term);
227 
228  return TRUE;
229 }
230 
231 static gboolean
232 vendor_addr_handler (xmlNodePtr node, gpointer vendor_pdata)
233 {
234  struct vendor_pdata *pdata = vendor_pdata;
235 
236  return gnc_dom_tree_to_address (node, gncVendorGetAddr(pdata->vendor));
237 }
238 
239 static gboolean
240 vendor_taxincluded_handler (xmlNodePtr node, gpointer vendor_pdata)
241 {
242  struct vendor_pdata *pdata = vendor_pdata;
243  GncTaxIncluded type;
244  char *str;
245  gboolean ret;
246 
247  str = dom_tree_to_text (node);
248  g_return_val_if_fail (str, FALSE);
249 
250  ret = gncTaxIncludedStringToType (str, &type);
251  g_free (str);
252 
253  if (ret)
254  gncVendorSetTaxIncluded(pdata->vendor, type);
255 
256  return ret;
257 }
258 
259 static gboolean
260 vendor_active_handler (xmlNodePtr node, gpointer vendor_pdata)
261 {
262  struct vendor_pdata *pdata = vendor_pdata;
263  return set_boolean (node, pdata->vendor, gncVendorSetActive);
264 }
265 
266 static gboolean
267 vendor_currency_handler (xmlNodePtr node, gpointer vendor_pdata)
268 {
269  struct vendor_pdata *pdata = vendor_pdata;
270  gnc_commodity *com;
271 
272  com = dom_tree_to_commodity_ref(node, pdata->book);
273  g_return_val_if_fail (com, FALSE);
274 
275  gncVendorSetCurrency (pdata->vendor, com);
276 
277  return TRUE;
278 }
279 
280 static gboolean
281 vendor_taxtable_handler (xmlNodePtr node, gpointer vendor_pdata)
282 {
283  struct vendor_pdata *pdata = vendor_pdata;
284  GncGUID *guid;
285  GncTaxTable *taxtable;
286 
287  guid = dom_tree_to_guid (node);
288  g_return_val_if_fail (guid, FALSE);
289  taxtable = gncTaxTableLookup (pdata->book, guid);
290  if (!taxtable)
291  {
292  taxtable = gncTaxTableCreate (pdata->book);
293  gncTaxTableBeginEdit (taxtable);
294  gncTaxTableSetGUID (taxtable, guid);
295  gncTaxTableCommitEdit (taxtable);
296  }
297  else
298  gncTaxTableDecRef (taxtable);
299 
300  gncVendorSetTaxTable (pdata->vendor, taxtable);
301  g_free(guid);
302  return TRUE;
303 }
304 
305 static gboolean
306 vendor_taxtableoverride_handler (xmlNodePtr node, gpointer vendor_pdata)
307 {
308  struct vendor_pdata *pdata = vendor_pdata;
309  return set_boolean (node, pdata->vendor, gncVendorSetTaxTableOverride);
310 }
311 
312 static gboolean
313 vendor_slots_handler (xmlNodePtr node, gpointer vendor_pdata)
314 {
315  struct vendor_pdata *pdata = vendor_pdata;
316  return dom_tree_to_kvp_frame_given (
317  node, qof_instance_get_slots (QOF_INSTANCE(pdata->vendor)));
318 
319 }
320 
321 static struct dom_tree_handler vendor_handlers_v2[] =
322 {
323  { vendor_name_string, vendor_name_handler, 1, 0 },
324  { vendor_guid_string, vendor_guid_handler, 1, 0 },
325  { vendor_id_string, vendor_id_handler, 1, 0 },
326  { vendor_addr_string, vendor_addr_handler, 1, 0 },
327  { vendor_notes_string, vendor_notes_handler, 0, 0 },
328  { vendor_terms_string, vendor_terms_handler, 0, 0 },
329  { vendor_taxincluded_string, vendor_taxincluded_handler, 1, 0 },
330  { vendor_active_string, vendor_active_handler, 1, 0 },
331  { vendor_currency_string, vendor_currency_handler, 0, 0 }, /* XXX */
332  { "vendor:commodity", vendor_currency_handler, 0, 0 }, /* XXX */
333  { vendor_taxtable_string, vendor_taxtable_handler, 0, 0 },
334  { vendor_taxtableoverride_string, vendor_taxtableoverride_handler, 0, 0 },
335  { vendor_slots_string, vendor_slots_handler, 0, 0 },
336  { NULL, 0, 0, 0 }
337 };
338 
339 static GncVendor*
340 dom_tree_to_vendor (xmlNodePtr node, QofBook *book)
341 {
342  struct vendor_pdata vendor_pdata;
343  gboolean successful;
344 
345  vendor_pdata.vendor = gncVendorCreate(book);
346  vendor_pdata.book = book;
347  gncVendorBeginEdit (vendor_pdata.vendor);
348 
349  successful = dom_tree_generic_parse (node, vendor_handlers_v2,
350  &vendor_pdata);
351 
352  if (successful)
353  gncVendorCommitEdit (vendor_pdata.vendor);
354  else
355  {
356  PERR ("failed to parse vendor tree");
357  gncVendorDestroy (vendor_pdata.vendor);
358  vendor_pdata.vendor = NULL;
359  }
360 
361  return vendor_pdata.vendor;
362 }
363 
364 static gboolean
365 gnc_vendor_end_handler(gpointer data_for_children,
366  GSList* data_from_children, GSList* sibling_data,
367  gpointer parent_data, gpointer global_data,
368  gpointer *result, const gchar *tag)
369 {
370  GncVendor *vendor;
371  xmlNodePtr tree = (xmlNodePtr)data_for_children;
372  gxpf_data *gdata = (gxpf_data*)global_data;
373  QofBook *book = gdata->bookdata;
374 
375  if (parent_data)
376  {
377  return TRUE;
378  }
379 
380  /* OK. For some messed up reason this is getting called again with a
381  NULL tag. So we ignore those cases */
382  if (!tag)
383  {
384  return TRUE;
385  }
386 
387  g_return_val_if_fail(tree, FALSE);
388 
389  vendor = dom_tree_to_vendor(tree, book);
390  if (vendor != NULL)
391  {
392  gdata->cb(tag, gdata->parsedata, vendor);
393  }
394 
395  xmlFreeNode(tree);
396 
397  return vendor != NULL;
398 }
399 
400 static sixtp *
401 vendor_sixtp_parser_create(void)
402 {
403  return sixtp_dom_parser_new(gnc_vendor_end_handler, NULL, NULL);
404 }
405 
406 static gboolean
407 vendor_should_be_saved (GncVendor *vendor)
408 {
409  const char *id;
410 
411  /* make sure this is a valid vendor before we save it -- should have an ID */
412  id = gncVendorGetID (vendor);
413  if (id == NULL || *id == '\0')
414  return FALSE;
415 
416  return TRUE;
417 }
418 
419 static void
420 do_count (QofInstance * vendor_p, gpointer count_p)
421 {
422  int *count = count_p;
423  if (vendor_should_be_saved ((GncVendor *)vendor_p))
424  (*count)++;
425 }
426 
427 static int
428 vendor_get_count (QofBook *book)
429 {
430  int count = 0;
431  qof_object_foreach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
432  return count;
433 }
434 
435 static void
436 xml_add_vendor (QofInstance * vendor_p, gpointer out_p)
437 {
438  xmlNodePtr node;
439  GncVendor *vendor = (GncVendor *) vendor_p;
440  FILE *out = out_p;
441 
442  if (ferror(out))
443  return;
444  if (!vendor_should_be_saved (vendor))
445  return;
446 
447  node = vendor_dom_tree_create (vendor);
448  xmlElemDump(out, NULL, node);
449  xmlFreeNode (node);
450  if (ferror(out) || fprintf(out, "\n") < 0)
451  return;
452 }
453 
454 static gboolean
455 vendor_write (FILE *out, QofBook *book)
456 {
457  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_vendor, (gpointer) out);
458  return ferror(out) == 0;
459 }
460 
461 static gboolean
462 vendor_ns(FILE *out)
463 {
464  g_return_val_if_fail(out, FALSE);
465  return gnc_xml2_write_namespace_decl(out, "vendor");
466 }
467 
468 void
469 gnc_vendor_xml_initialize (void)
470 {
471  static GncXmlDataType_t be_data =
472  {
473  GNC_FILE_BACKEND_VERS,
474  gnc_vendor_string,
475  vendor_sixtp_parser_create,
476  NULL, /* add_item */
477  vendor_get_count,
478  vendor_write,
479  NULL, /* scrub */
480  vendor_ns,
481  };
482 
483  qof_object_register_backend (_GNC_MOD_NAME,
485  &be_data);
486 }
gboolean qof_object_register_backend(QofIdTypeConst type_name, const char *backend_name, gpointer be_data)
Definition: sixtp.h:93
const GncGUID * qof_instance_get_guid(gconstpointer)
#define GNC_FILE_BACKEND
Definition: io-gncxml-v2.h:99
GncTaxIncluded
Definition: gncTaxTable.h:100
#define PERR(format, args...)
Definition: qoflog.h:237
Definition: guid.h:65
void qof_object_foreach_sorted(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
api for GnuCash version 2 XML-based file format
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
gboolean gnc_xml2_write_namespace_decl(FILE *out, const char *name_space)
const gchar * QofLogModule
Definition: qofid.h:89