1 /********************************************************************\
2 * gnc-book-xml-v2.c -- book xml i/o implementation *
3 * *
4 * Copyright (C) 2001 James LewisMoss <dres@debian.org> *
5 * Copyright (C) 2001 Linas Vepstas <linas@linas.org> *
6 * *
7 * This program is free software; you can redistribute it and/or *
8 * modify it under the terms of the GNU General Public License as *
9 * published by the Free Software Foundation; either version 2 of *
10 * the License, or (at your option) any later version. *
11 * *
12 * This program is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU General Public License*
18 * along with this program; if not, contact: *
19 * *
20 * Free Software Foundation Voice: +1-617-542-5942 *
21 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
22 * Boston, MA 02110-1301, USA gnu@gnu.org *
23 * *
24 \********************************************************************/
25 #include <glib.h>
26
27 extern "C"
28 {
29 #include <config.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include "qof.h"
33 }
34
35 #include "gnc-xml-helper.h"
36
37 #include "sixtp.h"
38 #include "sixtp-utils.h"
39 #include "sixtp-parsers.h"
40 #include "sixtp-utils.h"
41 #include "sixtp-dom-parsers.h"
42 #include "sixtp-dom-generators.h"
43
44 #include "gnc-xml.h"
45 #include "io-gncxml-gen.h"
46 #include "io-gncxml-v2.h"
47 #include "io-utils.h"
48
49 #include "sixtp-dom-parsers.h"
50
51 /* non-static because it's used in io-gncxml-v2.c */
52 const gchar* gnc_v2_book_version_string = "2.0.0";
53
54 /* ids */
55 #define gnc_book_string "gnc:book"
56 #define book_id_string "book:id"
57 #define book_slots_string "book:slots"
58
59 static QofLogModule log_module = GNC_MOD_IO;
60
61 /* ================================================================ */
62
63 xmlNodePtr
gnc_book_dom_tree_create(QofBook * book)64 gnc_book_dom_tree_create (QofBook* book)
65 {
66 xmlNodePtr ret;
67 G_GNUC_UNUSED gboolean allow_incompat = TRUE;
68
69 ret = xmlNewNode (NULL, BAD_CAST gnc_book_string);
70 xmlSetProp (ret, BAD_CAST "version", BAD_CAST gnc_v2_book_version_string);
71
72 xmlAddChild (ret, guid_to_dom_tree (book_id_string,
73 qof_book_get_guid (book)));
74
75 /* xmlAddChild won't do anything with a NULL, so tests are superfluous. */
76 xmlAddChild (ret, qof_instance_slots_to_dom_tree (book_slots_string,
77 QOF_INSTANCE (book)));
78
79 return ret;
80 }
81
82 /* ================================================================ */
83 /* same as above, but we write out directly. Only handle the guid
84 * and slots, everything else is handled elsewhere */
85
86 gboolean
write_book_parts(FILE * out,QofBook * book)87 write_book_parts (FILE* out, QofBook* book)
88 {
89 xmlNodePtr domnode, slotsnode;
90
91 domnode = guid_to_dom_tree (book_id_string, qof_book_get_guid (book));
92 xmlElemDump (out, NULL, domnode);
93 xmlFreeNode (domnode);
94
95 if (ferror (out) || fprintf (out, "\n") < 0)
96 return FALSE;
97
98
99 slotsnode = qof_instance_slots_to_dom_tree (book_slots_string,
100 QOF_INSTANCE (book));
101 if (slotsnode)
102 {
103 xmlElemDump (out, NULL, slotsnode);
104 xmlFreeNode (slotsnode);
105
106 if (ferror (out) || fprintf (out, "\n") < 0)
107 return FALSE;
108 }
109
110 return TRUE;
111 }
112
113
114 /* ================================================================ */
115
116 static gboolean
book_id_handler(xmlNodePtr node,gpointer book_pdata)117 book_id_handler (xmlNodePtr node, gpointer book_pdata)
118 {
119 QofBook* book = static_cast<decltype (book)> (book_pdata);
120 GncGUID* guid;
121
122 guid = dom_tree_to_guid (node);
123 qof_instance_set_guid (QOF_INSTANCE (book), guid);
124 guid_free (guid);
125
126 return TRUE;
127 }
128
129 static gboolean
book_slots_handler(xmlNodePtr node,gpointer book_pdata)130 book_slots_handler (xmlNodePtr node, gpointer book_pdata)
131 {
132 QofBook* book = static_cast<decltype (book)> (book_pdata);
133 gboolean success;
134
135 /* the below works only because the get is guaranteed to return
136 * a frame, even if its empty */
137 success = dom_tree_create_instance_slots (node, QOF_INSTANCE (book));
138
139 g_return_val_if_fail (success, FALSE);
140
141 return TRUE;
142 }
143
144
145 static struct dom_tree_handler book_handlers_v2[] =
146 {
147 { book_id_string, book_id_handler, 1, 0 },
148 { book_slots_string, book_slots_handler, 0, 0 },
149 { NULL, 0, 0, 0 }
150 };
151
152 static gboolean
gnc_book_end_handler(gpointer data_for_children,GSList * data_from_children,GSList * sibling_data,gpointer parent_data,gpointer global_data,gpointer * result,const gchar * tag)153 gnc_book_end_handler (gpointer data_for_children,
154 GSList* data_from_children, GSList* sibling_data,
155 gpointer parent_data, gpointer global_data,
156 gpointer* result, const gchar* tag)
157 {
158 xmlNodePtr tree = (xmlNodePtr)data_for_children;
159 gxpf_data* gdata = (gxpf_data*)global_data;
160 QofBook* book = static_cast<decltype (book)> (gdata->bookdata);
161
162
163 if (parent_data) return TRUE;
164
165 /* OK. For some messed up reason this is getting called again with a
166 NULL tag. So we ignore those cases */
167 if (!tag) return TRUE;
168
169 g_return_val_if_fail (tree, FALSE);
170
171 book = dom_tree_to_book (tree, book);
172 if (!book)
173 gdata->cb (tag, gdata->parsedata, book);
174
175 xmlFreeNode (tree);
176
177 return book != NULL;
178 }
179
180 static gboolean
gnc_book_id_end_handler(gpointer data_for_children,GSList * data_from_children,GSList * sibling_data,gpointer parent_data,gpointer global_data,gpointer * result,const gchar * tag)181 gnc_book_id_end_handler (gpointer data_for_children,
182 GSList* data_from_children, GSList* sibling_data,
183 gpointer parent_data, gpointer global_data,
184 gpointer* result, const gchar* tag)
185 {
186 gboolean successful;
187 xmlNodePtr tree = (xmlNodePtr)data_for_children;
188 gxpf_data* gdata = (gxpf_data*)global_data;
189 QofBook* book = static_cast<decltype (book)> (gdata->bookdata);
190
191 if (parent_data) return TRUE;
192 if (!tag) return TRUE;
193
194 g_return_val_if_fail (tree, FALSE);
195
196 successful = book_id_handler (tree, book);
197 xmlFreeNode (tree);
198
199 return successful;
200 }
201
202 static gboolean
gnc_book_slots_end_handler(gpointer data_for_children,GSList * data_from_children,GSList * sibling_data,gpointer parent_data,gpointer global_data,gpointer * result,const gchar * tag)203 gnc_book_slots_end_handler (gpointer data_for_children,
204 GSList* data_from_children, GSList* sibling_data,
205 gpointer parent_data, gpointer global_data,
206 gpointer* result, const gchar* tag)
207 {
208 gboolean successful;
209 xmlNodePtr tree = (xmlNodePtr)data_for_children;
210 gxpf_data* gdata = (gxpf_data*)global_data;
211 QofBook* book = static_cast<decltype (book)> (gdata->bookdata);
212
213 if (parent_data) return TRUE;
214 if (!tag) return TRUE;
215
216 g_return_val_if_fail (tree, FALSE);
217
218 successful = book_slots_handler (tree, book);
219 xmlFreeNode (tree);
220
221 return successful;
222 }
223
224 QofBook*
dom_tree_to_book(xmlNodePtr node,QofBook * book)225 dom_tree_to_book (xmlNodePtr node, QofBook* book)
226 {
227 gboolean successful;
228
229 successful = dom_tree_generic_parse (node, book_handlers_v2,
230 book);
231 if (!successful)
232 {
233 PERR ("failed to parse book");
234 book = NULL;
235 }
236
237 return book;
238 }
239
240 sixtp*
gnc_book_sixtp_parser_create(void)241 gnc_book_sixtp_parser_create (void)
242 {
243 return sixtp_dom_parser_new (gnc_book_end_handler, NULL, NULL);
244 }
245
246 sixtp*
gnc_book_id_sixtp_parser_create(void)247 gnc_book_id_sixtp_parser_create (void)
248 {
249 return sixtp_dom_parser_new (gnc_book_id_end_handler, NULL, NULL);
250 }
251
252 sixtp*
gnc_book_slots_sixtp_parser_create(void)253 gnc_book_slots_sixtp_parser_create (void)
254 {
255 return sixtp_dom_parser_new (gnc_book_slots_end_handler, NULL, NULL);
256 }
257