GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-employee-xml-v2.c
1 /********************************************************************\
2  * gnc-employee-xml-v2.c -- employee 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 "gncEmployeeP.h"
45 #include "gnc-employee-xml-v2.h"
46 #include "gnc-address-xml-v2.h"
47 
48 #define _GNC_MOD_NAME GNC_ID_EMPLOYEE
49 
50 static QofLogModule log_module = GNC_MOD_IO;
51 
52 const gchar *employee_version_string = "2.0.0";
53 
54 /* ids */
55 #define gnc_employee_string "gnc:GncEmployee"
56 #define employee_username_string "employee:username"
57 #define employee_guid_string "employee:guid"
58 #define employee_id_string "employee:id"
59 #define employee_addr_string "employee:addr"
60 #define employee_language_string "employee:language"
61 #define employee_acl_string "employee:acl"
62 #define employee_active_string "employee:active"
63 #define employee_workday_string "employee:workday"
64 #define employee_rate_string "employee:rate"
65 #define employee_currency_string "employee:currency"
66 #define employee_ccard_string "employee:ccard"
67 #define employee_slots_string "employee:slots"
68 
69 static void
70 maybe_add_string (xmlNodePtr ptr, const char *tag, const char *str)
71 {
72  if (str && strlen(str) > 0)
73  xmlAddChild (ptr, text_to_dom_tree (tag, str));
74 }
75 
76 static xmlNodePtr
77 employee_dom_tree_create (GncEmployee *employee)
78 {
79  xmlNodePtr ret, kvpnode;
80  gnc_numeric num;
81  Account* ccard_acc;
82 
83  ret = xmlNewNode(NULL, BAD_CAST gnc_employee_string);
84  xmlSetProp(ret, BAD_CAST "version", BAD_CAST employee_version_string);
85 
86  xmlAddChild(ret, guid_to_dom_tree(employee_guid_string,
87  qof_instance_get_guid(QOF_INSTANCE (employee))));
88 
89  xmlAddChild(ret, text_to_dom_tree(employee_username_string,
90  gncEmployeeGetUsername (employee)));
91 
92  xmlAddChild(ret, text_to_dom_tree(employee_id_string,
93  gncEmployeeGetID (employee)));
94 
95  xmlAddChild(ret, gnc_address_to_dom_tree(employee_addr_string,
96  gncEmployeeGetAddr (employee)));
97 
98  maybe_add_string (ret, employee_language_string,
99  gncEmployeeGetLanguage (employee));
100  maybe_add_string (ret, employee_acl_string, gncEmployeeGetAcl (employee));
101 
102  xmlAddChild(ret, int_to_dom_tree(employee_active_string,
103  gncEmployeeGetActive (employee)));
104 
105  num = gncEmployeeGetWorkday (employee);
106  xmlAddChild(ret, gnc_numeric_to_dom_tree (employee_workday_string, &num));
107 
108  num = gncEmployeeGetRate (employee);
109  xmlAddChild(ret, gnc_numeric_to_dom_tree (employee_rate_string, &num));
110 
111  xmlAddChild
112  (ret,
113  commodity_ref_to_dom_tree(employee_currency_string,
114  gncEmployeeGetCurrency (employee)));
115 
116  ccard_acc = gncEmployeeGetCCard (employee);
117  if (ccard_acc)
118  xmlAddChild(ret, guid_to_dom_tree(employee_ccard_string,
119  qof_instance_get_guid(QOF_INSTANCE(ccard_acc))));
120 
121  kvpnode = kvp_frame_to_dom_tree (employee_slots_string,
122  qof_instance_get_slots (QOF_INSTANCE(employee)));
123  if (kvpnode) xmlAddChild (ret, kvpnode);
124 
125  return ret;
126 }
127 
128 /***********************************************************************/
129 
131 {
132  GncEmployee *employee;
133  QofBook *book;
134 };
135 
136 static gboolean
137 set_string(xmlNodePtr node, GncEmployee* employee,
138  void (*func)(GncEmployee *employee, const char *txt))
139 {
140  char* txt = dom_tree_to_text(node);
141  g_return_val_if_fail(txt, FALSE);
142 
143  func(employee, txt);
144 
145  g_free(txt);
146 
147  return TRUE;
148 }
149 
150 static gboolean
151 employee_username_handler (xmlNodePtr node, gpointer employee_pdata)
152 {
153  struct employee_pdata *pdata = employee_pdata;
154 
155  return set_string(node, pdata->employee, gncEmployeeSetUsername);
156 }
157 
158 static gboolean
159 employee_guid_handler (xmlNodePtr node, gpointer employee_pdata)
160 {
161  struct employee_pdata *pdata = employee_pdata;
162  GncGUID *guid;
163  GncEmployee *employee;
164 
165  guid = dom_tree_to_guid(node);
166  g_return_val_if_fail(guid, FALSE);
167 
168  /* See if we've already created this one */
169  employee = gncEmployeeLookup (pdata->book, guid);
170  if (employee)
171  {
172  gncEmployeeDestroy (pdata->employee);
173  pdata->employee = employee;
174  gncEmployeeBeginEdit (employee);
175  }
176  else
177  {
178  gncEmployeeSetGUID(pdata->employee, guid);
179  }
180 
181  g_free(guid);
182 
183  return TRUE;
184 }
185 
186 static gboolean
187 employee_id_handler (xmlNodePtr node, gpointer employee_pdata)
188 {
189  struct employee_pdata *pdata = employee_pdata;
190 
191  return set_string(node, pdata->employee, gncEmployeeSetID);
192 }
193 
194 static gboolean
195 employee_language_handler (xmlNodePtr node, gpointer employee_pdata)
196 {
197  struct employee_pdata *pdata = employee_pdata;
198 
199  return set_string(node, pdata->employee, gncEmployeeSetLanguage);
200 }
201 
202 static gboolean
203 employee_acl_handler (xmlNodePtr node, gpointer employee_pdata)
204 {
205  struct employee_pdata *pdata = employee_pdata;
206 
207  return set_string(node, pdata->employee, gncEmployeeSetAcl);
208 }
209 
210 static gboolean
211 employee_addr_handler (xmlNodePtr node, gpointer employee_pdata)
212 {
213  struct employee_pdata *pdata = employee_pdata;
214 
215  return gnc_dom_tree_to_address (node, gncEmployeeGetAddr(pdata->employee));
216 }
217 
218 static gboolean
219 employee_active_handler (xmlNodePtr node, gpointer employee_pdata)
220 {
221  struct employee_pdata *pdata = employee_pdata;
222  gint64 val;
223  gboolean ret;
224 
225  ret = dom_tree_to_integer(node, &val);
226  if (ret)
227  gncEmployeeSetActive(pdata->employee, (gboolean)val);
228 
229  return ret;
230 }
231 
232 static gboolean
233 employee_workday_handler (xmlNodePtr node, gpointer employee_pdata)
234 {
235  struct employee_pdata *pdata = employee_pdata;
236  gnc_numeric *val;
237 
238  val = dom_tree_to_gnc_numeric(node);
239  g_return_val_if_fail(val, FALSE);
240  gncEmployeeSetWorkday(pdata->employee, *val);
241  g_free(val);
242 
243  return TRUE;
244 }
245 
246 static gboolean
247 employee_rate_handler (xmlNodePtr node, gpointer employee_pdata)
248 {
249  struct employee_pdata *pdata = employee_pdata;
250  gnc_numeric *val;
251 
252  val = dom_tree_to_gnc_numeric(node);
253  g_return_val_if_fail(val, FALSE);
254  gncEmployeeSetRate(pdata->employee, *val);
255  g_free(val);
256 
257  return TRUE;
258 }
259 
260 static gboolean
261 employee_currency_handler (xmlNodePtr node, gpointer employee_pdata)
262 {
263  struct employee_pdata *pdata = employee_pdata;
264  gnc_commodity *com;
265 
266  com = dom_tree_to_commodity_ref(node, pdata->book);
267  g_return_val_if_fail (com, FALSE);
268 
269  gncEmployeeSetCurrency (pdata->employee, com);
270 
271  return TRUE;
272 }
273 
274 static gboolean
275 employee_ccard_handler (xmlNodePtr node, gpointer employee_pdata)
276 {
277  struct employee_pdata *pdata = employee_pdata;
278  GncGUID *guid;
279  Account *ccard_acc;
280 
281  guid = dom_tree_to_guid(node);
282  g_return_val_if_fail(guid, FALSE);
283 
284  ccard_acc = xaccAccountLookup (guid, pdata->book);
285  g_free(guid);
286 
287  g_return_val_if_fail (ccard_acc, FALSE);
288  gncEmployeeSetCCard (pdata->employee, ccard_acc);
289 
290  return TRUE;
291 }
292 
293 static gboolean
294 employee_slots_handler (xmlNodePtr node, gpointer employee_pdata)
295 {
296  struct employee_pdata *pdata = employee_pdata;
297  return dom_tree_to_kvp_frame_given (
298  node, qof_instance_get_slots (QOF_INSTANCE(pdata->employee)));
299 }
300 
301 static struct dom_tree_handler employee_handlers_v2[] =
302 {
303  { employee_username_string, employee_username_handler, 1, 0 },
304  { employee_guid_string, employee_guid_handler, 1, 0 },
305  { employee_id_string, employee_id_handler, 1, 0 },
306  { employee_addr_string, employee_addr_handler, 1, 0 },
307  { employee_language_string, employee_language_handler, 0, 0 },
308  { employee_acl_string, employee_acl_handler, 0, 0 },
309  { employee_active_string, employee_active_handler, 1, 0 },
310  { employee_workday_string, employee_workday_handler, 1, 0 },
311  { employee_rate_string, employee_rate_handler, 1, 0 },
312  { employee_currency_string, employee_currency_handler, 0, 0 }, /* XXX */
313  { "employee:commodity", employee_currency_handler, 0, 0 }, /* XXX */
314  { employee_ccard_string, employee_ccard_handler, 0, 0 },
315  { employee_slots_string, employee_slots_handler, 0, 0 },
316  { NULL, 0, 0, 0 }
317 };
318 
319 static GncEmployee*
320 dom_tree_to_employee (xmlNodePtr node, QofBook *book)
321 {
322  struct employee_pdata employee_pdata;
323  gboolean successful;
324 
325  employee_pdata.employee = gncEmployeeCreate(book);
326  employee_pdata.book = book;
327  gncEmployeeBeginEdit (employee_pdata.employee);
328 
329  successful = dom_tree_generic_parse (node, employee_handlers_v2,
330  &employee_pdata);
331  if (successful)
332  gncEmployeeCommitEdit (employee_pdata.employee);
333  else
334  {
335  PERR ("failed to parse employee tree");
336  gncEmployeeDestroy (employee_pdata.employee);
337  employee_pdata.employee = NULL;
338  }
339 
340  return employee_pdata.employee;
341 }
342 
343 static gboolean
344 gnc_employee_end_handler(gpointer data_for_children,
345  GSList* data_from_children, GSList* sibling_data,
346  gpointer parent_data, gpointer global_data,
347  gpointer *result, const gchar *tag)
348 {
349  GncEmployee *employee;
350  xmlNodePtr tree = (xmlNodePtr)data_for_children;
351  gxpf_data *gdata = (gxpf_data*)global_data;
352  QofBook *book = gdata->bookdata;
353 
354 
355  if (parent_data)
356  {
357  return TRUE;
358  }
359 
360  /* OK. For some messed up reason this is getting called again with a
361  NULL tag. So we ignore those cases */
362  if (!tag)
363  {
364  return TRUE;
365  }
366 
367  g_return_val_if_fail(tree, FALSE);
368 
369  employee = dom_tree_to_employee(tree, book);
370  if (employee != NULL)
371  {
372  gdata->cb(tag, gdata->parsedata, employee);
373  }
374 
375  xmlFreeNode(tree);
376 
377  return employee != NULL;
378 }
379 
380 static sixtp *
381 employee_sixtp_parser_create(void)
382 {
383  return sixtp_dom_parser_new(gnc_employee_end_handler, NULL, NULL);
384 }
385 
386 static gboolean
387 employee_should_be_saved (GncEmployee *employee)
388 {
389  const char *id;
390 
391  /* make sure this is a valid employee before we save it -- should have an ID */
392  id = gncEmployeeGetID (employee);
393  if (id == NULL || *id == '\0')
394  return FALSE;
395 
396  return TRUE;
397 }
398 
399 static void
400 do_count (QofInstance * employee_p, gpointer count_p)
401 {
402  int *count = count_p;
403  if (employee_should_be_saved ((GncEmployee *) employee_p))
404  (*count)++;
405 }
406 
407 static int
408 employee_get_count (QofBook *book)
409 {
410  int count = 0;
411  qof_object_foreach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
412  return count;
413 }
414 
415 static void
416 xml_add_employee (QofInstance * employee_p, gpointer out_p)
417 {
418  xmlNodePtr node;
419  GncEmployee *employee = (GncEmployee *) employee_p;
420  FILE *out = out_p;
421 
422  if (ferror(out))
423  return;
424  if (!employee_should_be_saved (employee))
425  return;
426 
427  node = employee_dom_tree_create (employee);
428  xmlElemDump(out, NULL, node);
429  xmlFreeNode (node);
430  if (ferror(out) || fprintf(out, "\n") < 0)
431  return;
432 }
433 
434 static gboolean
435 employee_write (FILE *out, QofBook *book)
436 {
437  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_employee, (gpointer) out);
438  return ferror(out) == 0;
439 }
440 
441 static gboolean
442 employee_ns(FILE *out)
443 {
444  g_return_val_if_fail(out, FALSE);
445  return gnc_xml2_write_namespace_decl(out, "employee");
446 }
447 
448 void
449 gnc_employee_xml_initialize (void)
450 {
451  static GncXmlDataType_t be_data =
452  {
453  GNC_FILE_BACKEND_VERS,
454  gnc_employee_string,
455  employee_sixtp_parser_create,
456  NULL, /* add_item */
457  employee_get_count,
458  employee_write,
459  NULL, /* scrub */
460  employee_ns,
461  };
462 
463  qof_object_register_backend (_GNC_MOD_NAME,
465  &be_data);
466 }
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
#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
Account * xaccAccountLookup(const GncGUID *guid, QofBook *book)
Definition: Account.c:1827