GnuCash c935c2f+
Loading...
Searching...
No Matches
gnc-vendor-xml-v2.cpp
1/********************************************************************\
2 * gnc-vendor-xml-v2.c -- vendor xml i/o implementation *
3 * *
4 * Copyright (C) 2002 Derek Atkins <warlord@MIT.EDU> *
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 gnu@gnu.org *
22 * *
23\********************************************************************/
24#include <glib.h>
25
26#include <config.h>
27#include <stdlib.h>
28#include <string.h>
29#include "gncBillTermP.h"
30#include "gncVendorP.h"
31#include "gncTaxTableP.h"
32
33#include "gnc-xml-helper.h"
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
45#include "gnc-vendor-xml-v2.h"
46#include "gnc-address-xml-v2.h"
47#include "xml-helpers.h"
48#include "gnc-bill-term-xml-v2.h"
49
50#define _GNC_MOD_NAME GNC_ID_VENDOR
51
52static QofLogModule log_module = GNC_MOD_IO;
53
54const gchar* vendor_version_string = "2.0.0";
55
56/* ids */
57#define gnc_vendor_string "gnc:GncVendor"
58#define vendor_name_string "vendor:name"
59#define vendor_guid_string "vendor:guid"
60#define vendor_id_string "vendor:id"
61#define vendor_addr_string "vendor:addr"
62#define vendor_notes_string "vendor:notes"
63#define vendor_terms_string "vendor:terms"
64#define vendor_taxincluded_string "vendor:taxincluded"
65#define vendor_active_string "vendor:active"
66#define vendor_currency_string "vendor:currency"
67#define vendor_taxtable_string "vendor:taxtable"
68#define vendor_taxtableoverride_string "vendor:use-tt"
69#define vendor_slots_string "vendor:slots"
70
71static xmlNodePtr
72vendor_dom_tree_create (GncVendor* vendor)
73{
74 xmlNodePtr ret;
75 GncBillTerm* term;
76 GncTaxTable* taxtable;
77
78 ret = xmlNewNode (NULL, BAD_CAST gnc_vendor_string);
79 xmlSetProp (ret, BAD_CAST "version", BAD_CAST vendor_version_string);
80
81 xmlAddChild (ret, guid_to_dom_tree (vendor_guid_string,
82 qof_instance_get_guid (QOF_INSTANCE (vendor))));
83
84 xmlAddChild (ret, text_to_dom_tree (vendor_name_string,
85 gncVendorGetName (vendor)));
86
87 xmlAddChild (ret, text_to_dom_tree (vendor_id_string,
88 gncVendorGetID (vendor)));
89
90 xmlAddChild (ret, gnc_address_to_dom_tree (vendor_addr_string,
91 gncVendorGetAddr (vendor)));
92
93 maybe_add_string (ret, vendor_notes_string, gncVendorGetNotes (vendor));
94
95 term = gncVendorGetTerms (vendor);
96 if (term)
97 xmlAddChild (ret, guid_to_dom_tree (vendor_terms_string,
98 qof_instance_get_guid (QOF_INSTANCE (term))));
99
100 xmlAddChild (ret, text_to_dom_tree (vendor_taxincluded_string,
101 gncTaxIncludedTypeToString (
102 gncVendorGetTaxIncluded (vendor))));
103
104 xmlAddChild (ret, int_to_dom_tree (vendor_active_string,
105 gncVendorGetActive (vendor)));
106
107 xmlAddChild
108 (ret,
109 commodity_ref_to_dom_tree (vendor_currency_string,
110 gncVendorGetCurrency (vendor)));
111
112 xmlAddChild (ret, int_to_dom_tree (vendor_taxtableoverride_string,
113 gncVendorGetTaxTableOverride (vendor)));
114 taxtable = gncVendorGetTaxTable (vendor);
115 if (taxtable)
116 xmlAddChild (ret, guid_to_dom_tree (vendor_taxtable_string,
117 qof_instance_get_guid (QOF_INSTANCE (taxtable))));
118
119 /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
120 xmlAddChild (ret, qof_instance_slots_to_dom_tree (vendor_slots_string,
121 QOF_INSTANCE (vendor)));
122 return ret;
123}
124
125/***********************************************************************/
126
128{
129 GncVendor* vendor;
130 QofBook* book;
131};
132
133static gboolean
134set_boolean (xmlNodePtr node, GncVendor* vendor,
135 void (*func) (GncVendor* vendor, gboolean b))
136{
137 gint64 val;
138 gboolean ret;
139
140 ret = dom_tree_to_integer (node, &val);
141 if (ret)
142 func (vendor, (gboolean)val);
143
144 return ret;
145}
146
147static gboolean
148vendor_name_handler (xmlNodePtr node, gpointer vendor_pdata)
149{
150 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
151
152 return apply_xmlnode_text (gncVendorSetName, pdata->vendor, node);
153}
154
155static gboolean
156vendor_guid_handler (xmlNodePtr node, gpointer vendor_pdata)
157{
158 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
159 GncVendor* vendor;
160
161 auto guid = dom_tree_to_guid (node);
162 g_return_val_if_fail (guid, FALSE);
163 vendor = gncVendorLookup (pdata->book, &*guid);
164 if (vendor)
165 {
166 gncVendorDestroy (pdata->vendor);
167 pdata->vendor = vendor;
168 gncVendorBeginEdit (vendor);
169 }
170 else
171 {
172 gncVendorSetGUID (pdata->vendor, &*guid);
173 }
174
175 return TRUE;
176}
177
178static gboolean
179vendor_id_handler (xmlNodePtr node, gpointer vendor_pdata)
180{
181 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
182
183 return apply_xmlnode_text (gncVendorSetID, pdata->vendor, node);
184}
185
186static gboolean
187vendor_notes_handler (xmlNodePtr node, gpointer vendor_pdata)
188{
189 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
190
191 return apply_xmlnode_text (gncVendorSetNotes, pdata->vendor, node);
192}
193
194static gboolean
195vendor_terms_handler (xmlNodePtr node, gpointer vendor_pdata)
196{
197 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
198 GncBillTerm* term;
199
200 auto guid = dom_tree_to_guid (node);
201 g_return_val_if_fail (guid, FALSE);
202 term = gnc_billterm_xml_find_or_create (pdata->book, &*guid);
203 g_assert (term);
204 gncVendorSetTerms (pdata->vendor, term);
205
206 return TRUE;
207}
208
209static gboolean
210vendor_addr_handler (xmlNodePtr node, gpointer vendor_pdata)
211{
212 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
213
214 return gnc_dom_tree_to_address (node, gncVendorGetAddr (pdata->vendor));
215}
216
217static gboolean
218vendor_taxincluded_handler (xmlNodePtr node, gpointer vendor_pdata)
219{
220 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
221 auto set_taxincluded = [](GncVendor* vendor, const char* str)
222 {
223 GncTaxIncluded type;
224 if (gncTaxIncludedStringToType (str, &type))
225 gncVendorSetTaxIncluded (vendor, type);
226 };
227 return apply_xmlnode_text (set_taxincluded, pdata->vendor, node);
228}
229
230static gboolean
231vendor_active_handler (xmlNodePtr node, gpointer vendor_pdata)
232{
233 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
234 return set_boolean (node, pdata->vendor, gncVendorSetActive);
235}
236
237static gboolean
238vendor_currency_handler (xmlNodePtr node, gpointer vendor_pdata)
239{
240 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
241 gnc_commodity* com;
242
243 com = dom_tree_to_commodity_ref (node, pdata->book);
244 g_return_val_if_fail (com, FALSE);
245
246 gncVendorSetCurrency (pdata->vendor, com);
247
248 return TRUE;
249}
250
251static gboolean
252vendor_taxtable_handler (xmlNodePtr node, gpointer vendor_pdata)
253{
254 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
255 GncTaxTable* taxtable;
256
257 auto guid = dom_tree_to_guid (node);
258 g_return_val_if_fail (guid, FALSE);
259 taxtable = gncTaxTableLookup (pdata->book, &*guid);
260 if (!taxtable)
261 {
262 taxtable = gncTaxTableCreate (pdata->book);
263 gncTaxTableBeginEdit (taxtable);
264 gncTaxTableSetGUID (taxtable, &*guid);
265 gncTaxTableCommitEdit (taxtable);
266 }
267 else
268 gncTaxTableDecRef (taxtable);
269
270 gncVendorSetTaxTable (pdata->vendor, taxtable);
271 return TRUE;
272}
273
274static gboolean
275vendor_taxtableoverride_handler (xmlNodePtr node, gpointer vendor_pdata)
276{
277 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
278 return set_boolean (node, pdata->vendor, gncVendorSetTaxTableOverride);
279}
280
281static gboolean
282vendor_slots_handler (xmlNodePtr node, gpointer vendor_pdata)
283{
284 struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
285 return dom_tree_create_instance_slots (node, QOF_INSTANCE (pdata->vendor));
286
287}
288
289static struct dom_tree_handler vendor_handlers_v2[] =
290{
291 { vendor_name_string, vendor_name_handler, 1, 0 },
292 { vendor_guid_string, vendor_guid_handler, 1, 0 },
293 { vendor_id_string, vendor_id_handler, 1, 0 },
294 { vendor_addr_string, vendor_addr_handler, 1, 0 },
295 { vendor_notes_string, vendor_notes_handler, 0, 0 },
296 { vendor_terms_string, vendor_terms_handler, 0, 0 },
297 { vendor_taxincluded_string, vendor_taxincluded_handler, 1, 0 },
298 { vendor_active_string, vendor_active_handler, 1, 0 },
299 { vendor_currency_string, vendor_currency_handler, 0, 0 }, /* XXX */
300 { "vendor:commodity", vendor_currency_handler, 0, 0 }, /* XXX */
301 { vendor_taxtable_string, vendor_taxtable_handler, 0, 0 },
302 { vendor_taxtableoverride_string, vendor_taxtableoverride_handler, 0, 0 },
303 { vendor_slots_string, vendor_slots_handler, 0, 0 },
304 { NULL, 0, 0, 0 }
305};
306
307static GncVendor*
308dom_tree_to_vendor (xmlNodePtr node, QofBook* book)
309{
311 gboolean successful;
312
313 vendor_pdata.vendor = gncVendorCreate (book);
314 vendor_pdata.book = book;
315 gncVendorBeginEdit (vendor_pdata.vendor);
316
317 successful = dom_tree_generic_parse (node, vendor_handlers_v2,
318 &vendor_pdata);
319
320 if (successful)
321 gncVendorCommitEdit (vendor_pdata.vendor);
322 else
323 {
324 PERR ("failed to parse vendor tree");
325 gncVendorDestroy (vendor_pdata.vendor);
326 vendor_pdata.vendor = NULL;
327 }
328
329 return vendor_pdata.vendor;
330}
331
332static gboolean
333gnc_vendor_end_handler (gpointer data_for_children,
334 GSList* data_from_children, GSList* sibling_data,
335 gpointer parent_data, gpointer global_data,
336 gpointer* result, const gchar* tag)
337{
338 GncVendor* vendor;
339 xmlNodePtr tree = (xmlNodePtr)data_for_children;
340 gxpf_data* gdata = (gxpf_data*)global_data;
341 QofBook* book = static_cast<decltype (book)> (gdata->bookdata);
342
343 if (parent_data)
344 {
345 return TRUE;
346 }
347
348 /* OK. For some messed up reason this is getting called again with a
349 NULL tag. So we ignore those cases */
350 if (!tag)
351 {
352 return TRUE;
353 }
354
355 g_return_val_if_fail (tree, FALSE);
356
357 vendor = dom_tree_to_vendor (tree, book);
358 if (vendor != NULL)
359 {
360 gdata->cb (tag, gdata->parsedata, vendor);
361 }
362
363 xmlFreeNode (tree);
364
365 return vendor != NULL;
366}
367
368static sixtp*
369vendor_sixtp_parser_create (void)
370{
371 return sixtp_dom_parser_new (gnc_vendor_end_handler, NULL, NULL);
372}
373
374static gboolean
375vendor_should_be_saved (GncVendor* vendor)
376{
377 const char* id;
378
379 /* make sure this is a valid vendor before we save it -- should have an ID */
380 id = gncVendorGetID (vendor);
381 if (id == NULL || *id == '\0')
382 return FALSE;
383
384 return TRUE;
385}
386
387static void
388do_count (QofInstance* vendor_p, gpointer count_p)
389{
390 int* count = static_cast<decltype (count)> (count_p);
391 if (vendor_should_be_saved ((GncVendor*)vendor_p))
392 (*count)++;
393}
394
395static int
396vendor_get_count (QofBook* book)
397{
398 int count = 0;
399 qof_object_foreach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
400 return count;
401}
402
403static void
404xml_add_vendor (QofInstance* vendor_p, gpointer out_p)
405{
406 xmlNodePtr node;
407 GncVendor* vendor = (GncVendor*) vendor_p;
408 FILE* out = static_cast<decltype (out)> (out_p);
409
410 if (ferror (out))
411 return;
412 if (!vendor_should_be_saved (vendor))
413 return;
414
415 node = vendor_dom_tree_create (vendor);
416 xmlElemDump (out, NULL, node);
417 xmlFreeNode (node);
418 if (ferror (out) || fprintf (out, "\n") < 0)
419 return;
420}
421
422static gboolean
423vendor_write (FILE* out, QofBook* book)
424{
425 qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_vendor,
426 (gpointer) out);
427 return ferror (out) == 0;
428}
429
430static gboolean
431vendor_ns (FILE* out)
432{
433 g_return_val_if_fail (out, FALSE);
434 return gnc_xml2_write_namespace_decl (out, "vendor");
435}
436
437void
438gnc_vendor_xml_initialize (void)
439{
440 static GncXmlDataType_t be_data =
441 {
442 GNC_FILE_BACKEND_VERS,
443 gnc_vendor_string,
444 vendor_sixtp_parser_create,
445 NULL, /* add_item */
446 vendor_get_count,
447 vendor_write,
448 NULL, /* scrub */
449 vendor_ns,
450 };
451
452 gnc_xml_register_backend(be_data);
453}
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
#define PERR(format, args...)
Log a serious error.
Definition qoflog.h:244
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
Invoke the callback 'cb' on every instance ov a particular object type.
void qof_object_foreach_sorted(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
Invoke callback 'cb' on each instance in guid orted order.
GncTaxIncluded
How to interpret the TaxIncluded.
Definition gncTaxTable.h:86
api for GnuCash version 2 XML-based file format
modtime is the internal date of the last modtime See libgnucash/engine/TaxTableBillTermImmutability....
QofBook reference.
Definition qofbook-p.hpp:47
Definition sixtp.h:130