Branch data Line data Source code
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 : :
52 : : static QofLogModule log_module = GNC_MOD_IO;
53 : :
54 : : const 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 : :
71 : : static xmlNodePtr
72 : 2 : vendor_dom_tree_create (GncVendor* vendor)
73 : : {
74 : : xmlNodePtr ret;
75 : : GncBillTerm* term;
76 : : GncTaxTable* taxtable;
77 : :
78 : 2 : ret = xmlNewNode (NULL, BAD_CAST gnc_vendor_string);
79 : 2 : xmlSetProp (ret, BAD_CAST "version", BAD_CAST vendor_version_string);
80 : :
81 : 2 : xmlAddChild (ret, guid_to_dom_tree (vendor_guid_string,
82 : 2 : qof_instance_get_guid (QOF_INSTANCE (vendor))));
83 : :
84 : 2 : xmlAddChild (ret, text_to_dom_tree (vendor_name_string,
85 : : gncVendorGetName (vendor)));
86 : :
87 : 2 : xmlAddChild (ret, text_to_dom_tree (vendor_id_string,
88 : : gncVendorGetID (vendor)));
89 : :
90 : 2 : xmlAddChild (ret, gnc_address_to_dom_tree (vendor_addr_string,
91 : : gncVendorGetAddr (vendor)));
92 : :
93 : 2 : maybe_add_string (ret, vendor_notes_string, gncVendorGetNotes (vendor));
94 : :
95 : 2 : term = gncVendorGetTerms (vendor);
96 : 2 : if (term)
97 : 0 : xmlAddChild (ret, guid_to_dom_tree (vendor_terms_string,
98 : 0 : qof_instance_get_guid (QOF_INSTANCE (term))));
99 : :
100 : 2 : xmlAddChild (ret, text_to_dom_tree (vendor_taxincluded_string,
101 : : gncTaxIncludedTypeToString (
102 : : gncVendorGetTaxIncluded (vendor))));
103 : :
104 : 2 : xmlAddChild (ret, int_to_dom_tree (vendor_active_string,
105 : 2 : gncVendorGetActive (vendor)));
106 : :
107 : : xmlAddChild
108 : 2 : (ret,
109 : : commodity_ref_to_dom_tree (vendor_currency_string,
110 : 2 : gncVendorGetCurrency (vendor)));
111 : :
112 : 2 : xmlAddChild (ret, int_to_dom_tree (vendor_taxtableoverride_string,
113 : 2 : gncVendorGetTaxTableOverride (vendor)));
114 : 2 : taxtable = gncVendorGetTaxTable (vendor);
115 : 2 : if (taxtable)
116 : 0 : xmlAddChild (ret, guid_to_dom_tree (vendor_taxtable_string,
117 : 0 : qof_instance_get_guid (QOF_INSTANCE (taxtable))));
118 : :
119 : : /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
120 : 2 : xmlAddChild (ret, qof_instance_slots_to_dom_tree (vendor_slots_string,
121 : 2 : QOF_INSTANCE (vendor)));
122 : 2 : return ret;
123 : : }
124 : :
125 : : /***********************************************************************/
126 : :
127 : : struct vendor_pdata
128 : : {
129 : : GncVendor* vendor;
130 : : QofBook* book;
131 : : };
132 : :
133 : : static gboolean
134 : 6 : set_string (xmlNodePtr node, GncVendor* vendor,
135 : : void (*func) (GncVendor* vendor, const char* txt))
136 : : {
137 : 6 : char* txt = dom_tree_to_text (node);
138 : 6 : g_return_val_if_fail (txt, FALSE);
139 : :
140 : 6 : func (vendor, txt);
141 : :
142 : 6 : g_free (txt);
143 : :
144 : 6 : return TRUE;
145 : : }
146 : :
147 : : static gboolean
148 : 6 : set_boolean (xmlNodePtr node, GncVendor* vendor,
149 : : void (*func) (GncVendor* vendor, gboolean b))
150 : : {
151 : : gint64 val;
152 : : gboolean ret;
153 : :
154 : 6 : ret = dom_tree_to_integer (node, &val);
155 : 6 : if (ret)
156 : 6 : func (vendor, (gboolean)val);
157 : :
158 : 6 : return ret;
159 : : }
160 : :
161 : : static gboolean
162 : 3 : vendor_name_handler (xmlNodePtr node, gpointer vendor_pdata)
163 : : {
164 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
165 : :
166 : 3 : return set_string (node, pdata->vendor, gncVendorSetName);
167 : : }
168 : :
169 : : static gboolean
170 : 3 : vendor_guid_handler (xmlNodePtr node, gpointer vendor_pdata)
171 : : {
172 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
173 : : GncGUID* guid;
174 : : GncVendor* vendor;
175 : :
176 : 3 : guid = dom_tree_to_guid (node);
177 : 3 : g_return_val_if_fail (guid, FALSE);
178 : 3 : vendor = gncVendorLookup (pdata->book, guid);
179 : 3 : if (vendor)
180 : : {
181 : 3 : gncVendorDestroy (pdata->vendor);
182 : 3 : pdata->vendor = vendor;
183 : 3 : gncVendorBeginEdit (vendor);
184 : : }
185 : : else
186 : : {
187 : 0 : gncVendorSetGUID (pdata->vendor, guid);
188 : : }
189 : :
190 : 3 : guid_free (guid);
191 : :
192 : 3 : return TRUE;
193 : : }
194 : :
195 : : static gboolean
196 : 3 : vendor_id_handler (xmlNodePtr node, gpointer vendor_pdata)
197 : : {
198 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
199 : :
200 : 3 : return set_string (node, pdata->vendor, gncVendorSetID);
201 : : }
202 : :
203 : : static gboolean
204 : 0 : vendor_notes_handler (xmlNodePtr node, gpointer vendor_pdata)
205 : : {
206 : 0 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
207 : :
208 : 0 : return set_string (node, pdata->vendor, gncVendorSetNotes);
209 : : }
210 : :
211 : : static gboolean
212 : 0 : vendor_terms_handler (xmlNodePtr node, gpointer vendor_pdata)
213 : : {
214 : 0 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
215 : : GncGUID* guid;
216 : : GncBillTerm* term;
217 : :
218 : 0 : guid = dom_tree_to_guid (node);
219 : 0 : g_return_val_if_fail (guid, FALSE);
220 : 0 : term = gnc_billterm_xml_find_or_create (pdata->book, guid);
221 : 0 : g_assert (term);
222 : 0 : guid_free (guid);
223 : 0 : gncVendorSetTerms (pdata->vendor, term);
224 : :
225 : 0 : return TRUE;
226 : : }
227 : :
228 : : static gboolean
229 : 3 : vendor_addr_handler (xmlNodePtr node, gpointer vendor_pdata)
230 : : {
231 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
232 : :
233 : 3 : return gnc_dom_tree_to_address (node, gncVendorGetAddr (pdata->vendor));
234 : : }
235 : :
236 : : static gboolean
237 : 3 : vendor_taxincluded_handler (xmlNodePtr node, gpointer vendor_pdata)
238 : : {
239 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
240 : : GncTaxIncluded type;
241 : : char* str;
242 : : gboolean ret;
243 : :
244 : 3 : str = dom_tree_to_text (node);
245 : 3 : g_return_val_if_fail (str, FALSE);
246 : :
247 : 3 : ret = gncTaxIncludedStringToType (str, &type);
248 : 3 : g_free (str);
249 : :
250 : 3 : if (ret)
251 : 3 : gncVendorSetTaxIncluded (pdata->vendor, type);
252 : :
253 : 3 : return ret;
254 : : }
255 : :
256 : : static gboolean
257 : 3 : vendor_active_handler (xmlNodePtr node, gpointer vendor_pdata)
258 : : {
259 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
260 : 3 : return set_boolean (node, pdata->vendor, gncVendorSetActive);
261 : : }
262 : :
263 : : static gboolean
264 : 3 : vendor_currency_handler (xmlNodePtr node, gpointer vendor_pdata)
265 : : {
266 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
267 : : gnc_commodity* com;
268 : :
269 : 3 : com = dom_tree_to_commodity_ref (node, pdata->book);
270 : 3 : g_return_val_if_fail (com, FALSE);
271 : :
272 : 3 : gncVendorSetCurrency (pdata->vendor, com);
273 : :
274 : 3 : return TRUE;
275 : : }
276 : :
277 : : static gboolean
278 : 0 : vendor_taxtable_handler (xmlNodePtr node, gpointer vendor_pdata)
279 : : {
280 : 0 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
281 : : GncGUID* guid;
282 : : GncTaxTable* taxtable;
283 : :
284 : 0 : guid = dom_tree_to_guid (node);
285 : 0 : g_return_val_if_fail (guid, FALSE);
286 : 0 : taxtable = gncTaxTableLookup (pdata->book, guid);
287 : 0 : if (!taxtable)
288 : : {
289 : 0 : taxtable = gncTaxTableCreate (pdata->book);
290 : 0 : gncTaxTableBeginEdit (taxtable);
291 : 0 : gncTaxTableSetGUID (taxtable, guid);
292 : 0 : gncTaxTableCommitEdit (taxtable);
293 : : }
294 : : else
295 : 0 : gncTaxTableDecRef (taxtable);
296 : :
297 : 0 : gncVendorSetTaxTable (pdata->vendor, taxtable);
298 : 0 : guid_free (guid);
299 : 0 : return TRUE;
300 : : }
301 : :
302 : : static gboolean
303 : 3 : vendor_taxtableoverride_handler (xmlNodePtr node, gpointer vendor_pdata)
304 : : {
305 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
306 : 3 : return set_boolean (node, pdata->vendor, gncVendorSetTaxTableOverride);
307 : : }
308 : :
309 : : static gboolean
310 : 2 : vendor_slots_handler (xmlNodePtr node, gpointer vendor_pdata)
311 : : {
312 : 2 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
313 : 2 : return dom_tree_create_instance_slots (node, QOF_INSTANCE (pdata->vendor));
314 : :
315 : : }
316 : :
317 : : static struct dom_tree_handler vendor_handlers_v2[] =
318 : : {
319 : : { vendor_name_string, vendor_name_handler, 1, 0 },
320 : : { vendor_guid_string, vendor_guid_handler, 1, 0 },
321 : : { vendor_id_string, vendor_id_handler, 1, 0 },
322 : : { vendor_addr_string, vendor_addr_handler, 1, 0 },
323 : : { vendor_notes_string, vendor_notes_handler, 0, 0 },
324 : : { vendor_terms_string, vendor_terms_handler, 0, 0 },
325 : : { vendor_taxincluded_string, vendor_taxincluded_handler, 1, 0 },
326 : : { vendor_active_string, vendor_active_handler, 1, 0 },
327 : : { vendor_currency_string, vendor_currency_handler, 0, 0 }, /* XXX */
328 : : { "vendor:commodity", vendor_currency_handler, 0, 0 }, /* XXX */
329 : : { vendor_taxtable_string, vendor_taxtable_handler, 0, 0 },
330 : : { vendor_taxtableoverride_string, vendor_taxtableoverride_handler, 0, 0 },
331 : : { vendor_slots_string, vendor_slots_handler, 0, 0 },
332 : : { NULL, 0, 0, 0 }
333 : : };
334 : :
335 : : static GncVendor*
336 : 3 : dom_tree_to_vendor (xmlNodePtr node, QofBook* book)
337 : : {
338 : : struct vendor_pdata vendor_pdata;
339 : : gboolean successful;
340 : :
341 : 3 : vendor_pdata.vendor = gncVendorCreate (book);
342 : 3 : vendor_pdata.book = book;
343 : 3 : gncVendorBeginEdit (vendor_pdata.vendor);
344 : :
345 : 3 : successful = dom_tree_generic_parse (node, vendor_handlers_v2,
346 : : &vendor_pdata);
347 : :
348 : 3 : if (successful)
349 : 3 : gncVendorCommitEdit (vendor_pdata.vendor);
350 : : else
351 : : {
352 : 0 : PERR ("failed to parse vendor tree");
353 : 0 : gncVendorDestroy (vendor_pdata.vendor);
354 : 0 : vendor_pdata.vendor = NULL;
355 : : }
356 : :
357 : 3 : return vendor_pdata.vendor;
358 : : }
359 : :
360 : : static gboolean
361 : 55 : gnc_vendor_end_handler (gpointer data_for_children,
362 : : GSList* data_from_children, GSList* sibling_data,
363 : : gpointer parent_data, gpointer global_data,
364 : : gpointer* result, const gchar* tag)
365 : : {
366 : : GncVendor* vendor;
367 : 55 : xmlNodePtr tree = (xmlNodePtr)data_for_children;
368 : 55 : gxpf_data* gdata = (gxpf_data*)global_data;
369 : 55 : QofBook* book = static_cast<decltype (book)> (gdata->bookdata);
370 : :
371 : 55 : if (parent_data)
372 : : {
373 : 52 : return TRUE;
374 : : }
375 : :
376 : : /* OK. For some messed up reason this is getting called again with a
377 : : NULL tag. So we ignore those cases */
378 : 3 : if (!tag)
379 : : {
380 : 0 : return TRUE;
381 : : }
382 : :
383 : 3 : g_return_val_if_fail (tree, FALSE);
384 : :
385 : 3 : vendor = dom_tree_to_vendor (tree, book);
386 : 3 : if (vendor != NULL)
387 : : {
388 : 3 : gdata->cb (tag, gdata->parsedata, vendor);
389 : : }
390 : :
391 : 3 : xmlFreeNode (tree);
392 : :
393 : 3 : return vendor != NULL;
394 : : }
395 : :
396 : : static sixtp*
397 : 21 : vendor_sixtp_parser_create (void)
398 : : {
399 : 21 : return sixtp_dom_parser_new (gnc_vendor_end_handler, NULL, NULL);
400 : : }
401 : :
402 : : static gboolean
403 : 4 : vendor_should_be_saved (GncVendor* vendor)
404 : : {
405 : : const char* id;
406 : :
407 : : /* make sure this is a valid vendor before we save it -- should have an ID */
408 : 4 : id = gncVendorGetID (vendor);
409 : 4 : if (id == NULL || *id == '\0')
410 : 0 : return FALSE;
411 : :
412 : 4 : return TRUE;
413 : : }
414 : :
415 : : static void
416 : 2 : do_count (QofInstance* vendor_p, gpointer count_p)
417 : : {
418 : 2 : int* count = static_cast<decltype (count)> (count_p);
419 : 2 : if (vendor_should_be_saved ((GncVendor*)vendor_p))
420 : 2 : (*count)++;
421 : 2 : }
422 : :
423 : : static int
424 : 4 : vendor_get_count (QofBook* book)
425 : : {
426 : 4 : int count = 0;
427 : 4 : qof_object_foreach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
428 : 4 : return count;
429 : : }
430 : :
431 : : static void
432 : 2 : xml_add_vendor (QofInstance* vendor_p, gpointer out_p)
433 : : {
434 : : xmlNodePtr node;
435 : 2 : GncVendor* vendor = (GncVendor*) vendor_p;
436 : 2 : FILE* out = static_cast<decltype (out)> (out_p);
437 : :
438 : 2 : if (ferror (out))
439 : 0 : return;
440 : 2 : if (!vendor_should_be_saved (vendor))
441 : 0 : return;
442 : :
443 : 2 : node = vendor_dom_tree_create (vendor);
444 : 2 : xmlElemDump (out, NULL, node);
445 : 2 : xmlFreeNode (node);
446 : 2 : if (ferror (out) || fprintf (out, "\n") < 0)
447 : 0 : return;
448 : : }
449 : :
450 : : static gboolean
451 : 4 : vendor_write (FILE* out, QofBook* book)
452 : : {
453 : 4 : qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_vendor,
454 : : (gpointer) out);
455 : 4 : return ferror (out) == 0;
456 : : }
457 : :
458 : : static gboolean
459 : 4 : vendor_ns (FILE* out)
460 : : {
461 : 4 : g_return_val_if_fail (out, FALSE);
462 : 4 : return gnc_xml2_write_namespace_decl (out, "vendor");
463 : : }
464 : :
465 : : void
466 : 61 : gnc_vendor_xml_initialize (void)
467 : : {
468 : : static GncXmlDataType_t be_data =
469 : : {
470 : : GNC_FILE_BACKEND_VERS,
471 : : gnc_vendor_string,
472 : : vendor_sixtp_parser_create,
473 : : NULL, /* add_item */
474 : : vendor_get_count,
475 : : vendor_write,
476 : : NULL, /* scrub */
477 : : vendor_ns,
478 : : };
479 : :
480 : 61 : gnc_xml_register_backend(be_data);
481 : 61 : }
|