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_boolean (xmlNodePtr node, GncVendor* vendor,
135 : : void (*func) (GncVendor* vendor, gboolean b))
136 : : {
137 : : gint64 val;
138 : : gboolean ret;
139 : :
140 : 6 : ret = dom_tree_to_integer (node, &val);
141 : 6 : if (ret)
142 : 6 : func (vendor, (gboolean)val);
143 : :
144 : 6 : return ret;
145 : : }
146 : :
147 : : static gboolean
148 : 3 : vendor_name_handler (xmlNodePtr node, gpointer vendor_pdata)
149 : : {
150 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
151 : :
152 : 3 : return apply_xmlnode_text (gncVendorSetName, pdata->vendor, node);
153 : : }
154 : :
155 : : static gboolean
156 : 3 : vendor_guid_handler (xmlNodePtr node, gpointer vendor_pdata)
157 : : {
158 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
159 : : GncVendor* vendor;
160 : :
161 : 3 : auto guid = dom_tree_to_guid (node);
162 : 3 : g_return_val_if_fail (guid, FALSE);
163 : 3 : vendor = gncVendorLookup (pdata->book, &*guid);
164 : 3 : if (vendor)
165 : : {
166 : 3 : gncVendorDestroy (pdata->vendor);
167 : 3 : pdata->vendor = vendor;
168 : 3 : gncVendorBeginEdit (vendor);
169 : : }
170 : : else
171 : : {
172 : 0 : gncVendorSetGUID (pdata->vendor, &*guid);
173 : : }
174 : :
175 : 3 : return TRUE;
176 : : }
177 : :
178 : : static gboolean
179 : 3 : vendor_id_handler (xmlNodePtr node, gpointer vendor_pdata)
180 : : {
181 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
182 : :
183 : 3 : return apply_xmlnode_text (gncVendorSetID, pdata->vendor, node);
184 : : }
185 : :
186 : : static gboolean
187 : 0 : vendor_notes_handler (xmlNodePtr node, gpointer vendor_pdata)
188 : : {
189 : 0 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
190 : :
191 : 0 : return apply_xmlnode_text (gncVendorSetNotes, pdata->vendor, node);
192 : : }
193 : :
194 : : static gboolean
195 : 0 : vendor_terms_handler (xmlNodePtr node, gpointer vendor_pdata)
196 : : {
197 : 0 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
198 : : GncBillTerm* term;
199 : :
200 : 0 : auto guid = dom_tree_to_guid (node);
201 : 0 : g_return_val_if_fail (guid, FALSE);
202 : 0 : term = gnc_billterm_xml_find_or_create (pdata->book, &*guid);
203 : 0 : g_assert (term);
204 : 0 : gncVendorSetTerms (pdata->vendor, term);
205 : :
206 : 0 : return TRUE;
207 : : }
208 : :
209 : : static gboolean
210 : 3 : vendor_addr_handler (xmlNodePtr node, gpointer vendor_pdata)
211 : : {
212 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
213 : :
214 : 3 : return gnc_dom_tree_to_address (node, gncVendorGetAddr (pdata->vendor));
215 : : }
216 : :
217 : : static gboolean
218 : 3 : vendor_taxincluded_handler (xmlNodePtr node, gpointer vendor_pdata)
219 : : {
220 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
221 : 3 : auto set_taxincluded = [](GncVendor* vendor, const char* str)
222 : : {
223 : : GncTaxIncluded type;
224 : 3 : if (gncTaxIncludedStringToType (str, &type))
225 : 3 : gncVendorSetTaxIncluded (vendor, type);
226 : 3 : };
227 : 6 : return apply_xmlnode_text (set_taxincluded, pdata->vendor, node);
228 : : }
229 : :
230 : : static gboolean
231 : 3 : vendor_active_handler (xmlNodePtr node, gpointer vendor_pdata)
232 : : {
233 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
234 : 3 : return set_boolean (node, pdata->vendor, gncVendorSetActive);
235 : : }
236 : :
237 : : static gboolean
238 : 3 : vendor_currency_handler (xmlNodePtr node, gpointer vendor_pdata)
239 : : {
240 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
241 : : gnc_commodity* com;
242 : :
243 : 3 : com = dom_tree_to_commodity_ref (node, pdata->book);
244 : 3 : g_return_val_if_fail (com, FALSE);
245 : :
246 : 3 : gncVendorSetCurrency (pdata->vendor, com);
247 : :
248 : 3 : return TRUE;
249 : : }
250 : :
251 : : static gboolean
252 : 0 : vendor_taxtable_handler (xmlNodePtr node, gpointer vendor_pdata)
253 : : {
254 : 0 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
255 : : GncTaxTable* taxtable;
256 : :
257 : 0 : auto guid = dom_tree_to_guid (node);
258 : 0 : g_return_val_if_fail (guid, FALSE);
259 : 0 : taxtable = gncTaxTableLookup (pdata->book, &*guid);
260 : 0 : if (!taxtable)
261 : : {
262 : 0 : taxtable = gncTaxTableCreate (pdata->book);
263 : 0 : gncTaxTableBeginEdit (taxtable);
264 : 0 : gncTaxTableSetGUID (taxtable, &*guid);
265 : 0 : gncTaxTableCommitEdit (taxtable);
266 : : }
267 : : else
268 : 0 : gncTaxTableDecRef (taxtable);
269 : :
270 : 0 : gncVendorSetTaxTable (pdata->vendor, taxtable);
271 : 0 : return TRUE;
272 : : }
273 : :
274 : : static gboolean
275 : 3 : vendor_taxtableoverride_handler (xmlNodePtr node, gpointer vendor_pdata)
276 : : {
277 : 3 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
278 : 3 : return set_boolean (node, pdata->vendor, gncVendorSetTaxTableOverride);
279 : : }
280 : :
281 : : static gboolean
282 : 2 : vendor_slots_handler (xmlNodePtr node, gpointer vendor_pdata)
283 : : {
284 : 2 : struct vendor_pdata* pdata = static_cast<decltype (pdata)> (vendor_pdata);
285 : 2 : return dom_tree_create_instance_slots (node, QOF_INSTANCE (pdata->vendor));
286 : :
287 : : }
288 : :
289 : : static 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 : :
307 : : static GncVendor*
308 : 3 : dom_tree_to_vendor (xmlNodePtr node, QofBook* book)
309 : : {
310 : : struct vendor_pdata vendor_pdata;
311 : : gboolean successful;
312 : :
313 : 3 : vendor_pdata.vendor = gncVendorCreate (book);
314 : 3 : vendor_pdata.book = book;
315 : 3 : gncVendorBeginEdit (vendor_pdata.vendor);
316 : :
317 : 3 : successful = dom_tree_generic_parse (node, vendor_handlers_v2,
318 : : &vendor_pdata);
319 : :
320 : 3 : if (successful)
321 : 3 : gncVendorCommitEdit (vendor_pdata.vendor);
322 : : else
323 : : {
324 : 0 : PERR ("failed to parse vendor tree");
325 : 0 : gncVendorDestroy (vendor_pdata.vendor);
326 : 0 : vendor_pdata.vendor = NULL;
327 : : }
328 : :
329 : 3 : return vendor_pdata.vendor;
330 : : }
331 : :
332 : : static gboolean
333 : 55 : gnc_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 : 55 : xmlNodePtr tree = (xmlNodePtr)data_for_children;
340 : 55 : gxpf_data* gdata = (gxpf_data*)global_data;
341 : 55 : QofBook* book = static_cast<decltype (book)> (gdata->bookdata);
342 : :
343 : 55 : if (parent_data)
344 : : {
345 : 52 : 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 : 3 : if (!tag)
351 : : {
352 : 0 : return TRUE;
353 : : }
354 : :
355 : 3 : g_return_val_if_fail (tree, FALSE);
356 : :
357 : 3 : vendor = dom_tree_to_vendor (tree, book);
358 : 3 : if (vendor != NULL)
359 : : {
360 : 3 : gdata->cb (tag, gdata->parsedata, vendor);
361 : : }
362 : :
363 : 3 : xmlFreeNode (tree);
364 : :
365 : 3 : return vendor != NULL;
366 : : }
367 : :
368 : : static sixtp*
369 : 22 : vendor_sixtp_parser_create (void)
370 : : {
371 : 22 : return sixtp_dom_parser_new (gnc_vendor_end_handler, NULL, NULL);
372 : : }
373 : :
374 : : static gboolean
375 : 4 : vendor_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 : 4 : id = gncVendorGetID (vendor);
381 : 4 : if (id == NULL || *id == '\0')
382 : 0 : return FALSE;
383 : :
384 : 4 : return TRUE;
385 : : }
386 : :
387 : : static void
388 : 2 : do_count (QofInstance* vendor_p, gpointer count_p)
389 : : {
390 : 2 : int* count = static_cast<decltype (count)> (count_p);
391 : 2 : if (vendor_should_be_saved ((GncVendor*)vendor_p))
392 : 2 : (*count)++;
393 : 2 : }
394 : :
395 : : static int
396 : 4 : vendor_get_count (QofBook* book)
397 : : {
398 : 4 : int count = 0;
399 : 4 : qof_object_foreach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
400 : 4 : return count;
401 : : }
402 : :
403 : : static void
404 : 2 : xml_add_vendor (QofInstance* vendor_p, gpointer out_p)
405 : : {
406 : : xmlNodePtr node;
407 : 2 : GncVendor* vendor = (GncVendor*) vendor_p;
408 : 2 : FILE* out = static_cast<decltype (out)> (out_p);
409 : :
410 : 2 : if (ferror (out))
411 : 0 : return;
412 : 2 : if (!vendor_should_be_saved (vendor))
413 : 0 : return;
414 : :
415 : 2 : node = vendor_dom_tree_create (vendor);
416 : 2 : xmlElemDump (out, NULL, node);
417 : 2 : xmlFreeNode (node);
418 : 2 : if (ferror (out) || fprintf (out, "\n") < 0)
419 : 0 : return;
420 : : }
421 : :
422 : : static gboolean
423 : 4 : vendor_write (FILE* out, QofBook* book)
424 : : {
425 : 4 : qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_vendor,
426 : : (gpointer) out);
427 : 4 : return ferror (out) == 0;
428 : : }
429 : :
430 : : static gboolean
431 : 4 : vendor_ns (FILE* out)
432 : : {
433 : 4 : g_return_val_if_fail (out, FALSE);
434 : 4 : return gnc_xml2_write_namespace_decl (out, "vendor");
435 : : }
436 : :
437 : : void
438 : 15 : gnc_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 : 15 : gnc_xml_register_backend(be_data);
453 : 15 : }
|