GnuCash  2.6.99
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
gnc-job-xml-v2.c
1 /********************************************************************\
2  * gnc-job-xml-v2.c -- job 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 "gncJobP.h"
45 #include "gnc-job-xml-v2.h"
46 #include "gnc-owner-xml-v2.h"
47 #include "xml-helpers.h"
48 
49 #define _GNC_MOD_NAME GNC_ID_JOB
50 
51 static QofLogModule log_module = GNC_MOD_IO;
52 
53 const gchar *job_version_string = "2.0.0";
54 
55 /* ids */
56 #define gnc_job_string "gnc:GncJob"
57 #define job_guid_string "job:guid"
58 #define job_id_string "job:id"
59 #define job_name_string "job:name"
60 #define job_reference_string "job:reference"
61 #define job_owner_string "job:owner"
62 #define job_active_string "job:active"
63 #define job_slots_string "job:slots"
64 
65 /* EFFECTIVE FRIEND FUNCTION */
66 extern KvpFrame *qof_instance_get_slots (const QofInstance*);
67 
68 static xmlNodePtr
69 job_dom_tree_create (GncJob *job)
70 {
71  xmlNodePtr ret;
72  KvpFrame *kf;
73 
74  ret = xmlNewNode(NULL, BAD_CAST gnc_job_string);
75  xmlSetProp(ret, BAD_CAST "version", BAD_CAST job_version_string);
76 
77  xmlAddChild(ret, guid_to_dom_tree(job_guid_string,
78  qof_instance_get_guid (QOF_INSTANCE (job))));
79 
80  xmlAddChild(ret, text_to_dom_tree(job_id_string,
81  gncJobGetID (job)));
82 
83  xmlAddChild(ret, text_to_dom_tree(job_name_string,
84  gncJobGetName (job)));
85 
86  maybe_add_string (ret, job_reference_string, gncJobGetReference (job));
87 
88  xmlAddChild(ret, gnc_owner_to_dom_tree (job_owner_string,
89  gncJobGetOwner (job)));
90 
91  xmlAddChild(ret, int_to_dom_tree(job_active_string,
92  gncJobGetActive (job)));
93 
94  kf = qof_instance_get_slots (QOF_INSTANCE(job));
95  if (kf)
96  {
97  xmlNodePtr kvpnode = kvp_frame_to_dom_tree(job_slots_string, kf);
98  if (kvpnode)
99  {
100  xmlAddChild(ret, kvpnode);
101  }
102  }
103 
104  return ret;
105 }
106 
107 /***********************************************************************/
108 
109 struct job_pdata
110 {
111  GncJob *job;
112  QofBook *book;
113 };
114 
115 static gboolean
116 set_string(xmlNodePtr node, GncJob* job,
117  void (*func)(GncJob *job, const char *txt))
118 {
119  char* txt = dom_tree_to_text(node);
120  g_return_val_if_fail(txt, FALSE);
121 
122  func(job, txt);
123 
124  g_free(txt);
125 
126  return TRUE;
127 }
128 
129 static gboolean
130 job_name_handler (xmlNodePtr node, gpointer job_pdata)
131 {
132  struct job_pdata *pdata = job_pdata;
133 
134  return set_string(node, pdata->job, gncJobSetName);
135 }
136 
137 static gboolean
138 job_guid_handler (xmlNodePtr node, gpointer job_pdata)
139 {
140  struct job_pdata *pdata = job_pdata;
141  GncGUID *guid;
142  GncJob *job;
143 
144  guid = dom_tree_to_guid(node);
145  g_return_val_if_fail(guid, FALSE);
146  job = gncJobLookup (pdata->book, guid);
147  if (job)
148  {
149  gncJobDestroy (pdata->job);
150  pdata->job = job;
151  gncJobBeginEdit (job);
152  }
153  else
154  {
155  gncJobSetGUID(pdata->job, guid);
156  }
157 
158  g_free(guid);
159 
160  return TRUE;
161 }
162 
163 static gboolean
164 job_id_handler (xmlNodePtr node, gpointer job_pdata)
165 {
166  struct job_pdata *pdata = job_pdata;
167 
168  return set_string(node, pdata->job, gncJobSetID);
169 }
170 
171 static gboolean
172 job_reference_handler (xmlNodePtr node, gpointer job_pdata)
173 {
174  struct job_pdata *pdata = job_pdata;
175 
176  return set_string(node, pdata->job, gncJobSetReference);
177 }
178 
179 static gboolean
180 job_owner_handler (xmlNodePtr node, gpointer job_pdata)
181 {
182  struct job_pdata *pdata = job_pdata;
183  GncOwner owner;
184  gboolean ret;
185 
186  ret = gnc_dom_tree_to_owner (node, &owner, pdata->book);
187  if (ret)
188  gncJobSetOwner (pdata->job, &owner);
189 
190  return ret;
191 }
192 
193 static gboolean
194 job_active_handler (xmlNodePtr node, gpointer job_pdata)
195 {
196  struct job_pdata *pdata = job_pdata;
197  gint64 val;
198  gboolean ret;
199 
200  ret = dom_tree_to_integer(node, &val);
201  if (ret)
202  gncJobSetActive(pdata->job, (gboolean)val);
203 
204  return ret;
205 }
206 
207 static gboolean
208 job_slots_handler (xmlNodePtr node, gpointer job_pdata)
209 {
210  struct job_pdata *pdata = job_pdata;
211 
212  return dom_tree_to_kvp_frame_given
213  (node, qof_instance_get_slots (QOF_INSTANCE (pdata->job)));
214 }
215 
216 static struct dom_tree_handler job_handlers_v2[] =
217 {
218  { job_guid_string, job_guid_handler, 1, 0 },
219  { job_id_string, job_id_handler, 1, 0 },
220  { job_name_string, job_name_handler, 1, 0 },
221  { job_reference_string, job_reference_handler, 0, 0 },
222  { job_owner_string, job_owner_handler, 1, 0 },
223  { job_active_string, job_active_handler, 1, 0 },
224  { job_slots_string, job_slots_handler, 0, 0 },
225  { NULL, 0, 0, 0 }
226 };
227 
228 static GncJob*
229 dom_tree_to_job (xmlNodePtr node, QofBook *book)
230 {
231  struct job_pdata job_pdata;
232  gboolean successful;
233 
234  job_pdata.job = gncJobCreate(book);
235  job_pdata.book = book;
236  gncJobBeginEdit (job_pdata.job);
237 
238  successful = dom_tree_generic_parse (node, job_handlers_v2,
239  &job_pdata);
240 
241  if (successful)
242  gncJobCommitEdit (job_pdata.job);
243  else
244  {
245  PERR ("failed to parse job tree");
246  gncJobDestroy (job_pdata.job);
247  job_pdata.job = NULL;
248  }
249 
250  return job_pdata.job;
251 }
252 
253 static gboolean
254 gnc_job_end_handler(gpointer data_for_children,
255  GSList* data_from_children, GSList* sibling_data,
256  gpointer parent_data, gpointer global_data,
257  gpointer *result, const gchar *tag)
258 {
259  GncJob *job;
260  xmlNodePtr tree = (xmlNodePtr)data_for_children;
261  gxpf_data *gdata = (gxpf_data*)global_data;
262  QofBook *book = gdata->bookdata;
263 
264  if (parent_data)
265  {
266  return TRUE;
267  }
268 
269  /* OK. For some messed up reason this is getting called again with a
270  NULL tag. So we ignore those cases */
271  if (!tag)
272  {
273  return TRUE;
274  }
275 
276  g_return_val_if_fail(tree, FALSE);
277 
278  job = dom_tree_to_job(tree, book);
279  if (job != NULL)
280  {
281  gdata->cb(tag, gdata->parsedata, job);
282  }
283 
284  xmlFreeNode(tree);
285 
286  return job != NULL;
287 }
288 
289 static sixtp *
290 job_sixtp_parser_create(void)
291 {
292  return sixtp_dom_parser_new(gnc_job_end_handler, NULL, NULL);
293 }
294 
295 static gboolean
296 job_should_be_saved (GncJob *job)
297 {
298  const char *id;
299 
300  /* make sure this is a valid job before we save it -- should have an ID */
301  id = gncJobGetID (job);
302  if (id == NULL || *id == '\0')
303  return FALSE;
304 
305  return TRUE;
306 }
307 
308 static void
309 do_count (QofInstance * job_p, gpointer count_p)
310 {
311  int *count = count_p;
312  if (job_should_be_saved ((GncJob *)job_p))
313  (*count)++;
314 }
315 
316 static int
317 job_get_count (QofBook *book)
318 {
319  int count = 0;
320  qof_object_foreach (_GNC_MOD_NAME, book, do_count, (gpointer) &count);
321  return count;
322 }
323 
324 static void
325 xml_add_job (QofInstance * job_p, gpointer out_p)
326 {
327  xmlNodePtr node;
328  GncJob *job = (GncJob *) job_p;
329  FILE *out = out_p;
330 
331  if (ferror(out))
332  return;
333  if (!job_should_be_saved (job))
334  return;
335 
336  node = job_dom_tree_create (job);
337  xmlElemDump(out, NULL, node);
338  xmlFreeNode (node);
339  if (ferror(out) || fprintf(out, "\n") < 0)
340  return;
341 }
342 
343 static gboolean
344 job_write (FILE *out, QofBook *book)
345 {
346  qof_object_foreach_sorted (_GNC_MOD_NAME, book, xml_add_job, (gpointer) out);
347  return ferror(out) == 0;
348 }
349 
350 static gboolean
351 job_ns(FILE *out)
352 {
353  g_return_val_if_fail(out, FALSE);
354  return gnc_xml2_write_namespace_decl(out, "job");
355 }
356 
357 void
358 gnc_job_xml_initialize (void)
359 {
360  static GncXmlDataType_t be_data =
361  {
362  GNC_FILE_BACKEND_VERS,
363  gnc_job_string,
364  job_sixtp_parser_create,
365  NULL, /* add_item */
366  job_get_count,
367  job_write,
368  NULL, /* scrub */
369  job_ns,
370  };
371 
372  qof_object_register_backend (_GNC_MOD_NAME,
374  &be_data);
375 }
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)
Definition: gncJob.c:41
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)
struct KvpFrameImpl KvpFrame
Definition: kvp_frame.h:76
const gchar * QofLogModule
Definition: qofid.h:89