Branch data Line data Source code
1 : : /********************************************************************\
2 : : * gnc-commodity-xml-v2.c -- commodity xml i/o implementation *
3 : : * *
4 : : * Copyright (C) 2001 James LewisMoss <dres@debian.org> *
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 <string.h>
28 : : #include "AccountP.hpp"
29 : : #include "Account.h"
30 : :
31 : : #include "gnc-xml-helper.h"
32 : : #include "sixtp.h"
33 : : #include "sixtp-utils.h"
34 : : #include "sixtp-parsers.h"
35 : : #include "sixtp-utils.h"
36 : : #include "sixtp-dom-parsers.h"
37 : : #include "sixtp-dom-generators.h"
38 : :
39 : : #include "gnc-xml.h"
40 : : #include "io-gncxml-gen.h"
41 : :
42 : : static QofLogModule log_module = GNC_MOD_IO;
43 : :
44 : : const gchar* commodity_version_string = "2.0.0";
45 : :
46 : : /* ids */
47 : : #define gnc_commodity_string "gnc:commodity"
48 : : #define cmdty_namespace "cmdty:space"
49 : : #define cmdty_id "cmdty:id"
50 : : #define cmdty_name "cmdty:name"
51 : : #define cmdty_xcode "cmdty:xcode"
52 : : #define cmdty_fraction "cmdty:fraction"
53 : : #define cmdty_get_quotes "cmdty:get_quotes"
54 : : #define cmdty_quote_source "cmdty:quote_source"
55 : : #define cmdty_quote_tz "cmdty:quote_tz"
56 : : #define cmdty_slots "cmdty:slots"
57 : :
58 : : xmlNodePtr
59 : 932 : gnc_commodity_dom_tree_create (const gnc_commodity* com)
60 : : {
61 : : gnc_quote_source* source;
62 : : const char* string;
63 : : xmlNodePtr ret;
64 : 932 : gboolean currency = gnc_commodity_is_iso (com);
65 : : xmlNodePtr slotsnode =
66 : 932 : qof_instance_slots_to_dom_tree (cmdty_slots, QOF_INSTANCE (com));
67 : :
68 : 932 : if (currency && !gnc_commodity_get_quote_flag (com) && !slotsnode)
69 : 904 : return NULL;
70 : :
71 : 28 : ret = xmlNewNode (NULL, BAD_CAST gnc_commodity_string);
72 : :
73 : 28 : xmlSetProp (ret, BAD_CAST "version", BAD_CAST commodity_version_string);
74 : :
75 : 28 : xmlAddChild (ret, text_to_dom_tree (cmdty_namespace,
76 : : gnc_commodity_get_namespace (com)));
77 : 28 : xmlAddChild (ret, text_to_dom_tree (cmdty_id,
78 : : gnc_commodity_get_mnemonic (com)));
79 : :
80 : 28 : if (!currency)
81 : : {
82 : 24 : if (gnc_commodity_get_fullname (com))
83 : : {
84 : 24 : xmlAddChild (ret, text_to_dom_tree (cmdty_name,
85 : : gnc_commodity_get_fullname (com)));
86 : : }
87 : :
88 : 24 : const char* cusip = gnc_commodity_get_cusip (com);
89 : 24 : if (cusip && *cusip)
90 : : {
91 : 24 : xmlAddChild (ret, text_to_dom_tree (cmdty_xcode, cusip));
92 : : }
93 : :
94 : 24 : xmlAddChild (ret, int_to_dom_tree (cmdty_fraction,
95 : 24 : gnc_commodity_get_fraction (com)));
96 : : }
97 : :
98 : 28 : if (gnc_commodity_get_quote_flag (com))
99 : : {
100 : 4 : xmlNewChild (ret, NULL, BAD_CAST cmdty_get_quotes, NULL);
101 : 4 : source = gnc_commodity_get_quote_source (com);
102 : 4 : if (source)
103 : 4 : xmlAddChild (ret, text_to_dom_tree (cmdty_quote_source,
104 : : gnc_quote_source_get_internal_name (source)));
105 : 4 : string = gnc_commodity_get_quote_tz (com);
106 : 4 : if (string)
107 : 4 : xmlAddChild (ret, text_to_dom_tree (cmdty_quote_tz, string));
108 : : }
109 : :
110 : 28 : if (slotsnode)
111 : 0 : xmlAddChild (ret, slotsnode);
112 : :
113 : 28 : return ret;
114 : : }
115 : :
116 : : /***********************************************************************/
117 : :
118 : : struct com_char_handler
119 : : {
120 : : const char* tag;
121 : : void (*func) (gnc_commodity* com, const char* val);
122 : : };
123 : :
124 : : struct com_char_handler com_handlers[] =
125 : : {
126 : : { cmdty_namespace, gnc_commodity_set_namespace },
127 : : { cmdty_id, gnc_commodity_set_mnemonic },
128 : : { cmdty_name, gnc_commodity_set_fullname },
129 : : { cmdty_xcode, gnc_commodity_set_cusip },
130 : : { cmdty_quote_tz, gnc_commodity_set_quote_tz },
131 : : { 0, 0 }
132 : : };
133 : :
134 : : static void
135 : 1234 : set_commodity_value (xmlNodePtr node, gnc_commodity* com)
136 : : {
137 : 1234 : if (g_strcmp0 ((char*) node->name, cmdty_fraction) == 0)
138 : : {
139 : : gint64 val;
140 : : char* string;
141 : :
142 : 103 : string = (char*) xmlNodeGetContent (node->xmlChildrenNode);
143 : 103 : if (string_to_gint64 (string, &val))
144 : : {
145 : 103 : gnc_commodity_set_fraction (com, val);
146 : : }
147 : 103 : xmlFree (string);
148 : : }
149 : 1131 : else if (g_strcmp0 ((char*)node->name, cmdty_get_quotes) == 0)
150 : : {
151 : 20 : gnc_commodity_set_quote_flag (com, TRUE);
152 : : }
153 : 1111 : else if (g_strcmp0 ((char*)node->name, cmdty_quote_source) == 0)
154 : : {
155 : : gnc_quote_source* source;
156 : : char* string;
157 : :
158 : 20 : string = (char*) xmlNodeGetContent (node->xmlChildrenNode);
159 : 20 : source = gnc_quote_source_lookup_by_internal (string);
160 : 20 : if (!source)
161 : 0 : source = gnc_quote_source_add_new (string, FALSE);
162 : 20 : gnc_commodity_set_quote_source (com, source);
163 : 20 : xmlFree (string);
164 : : }
165 : 1091 : else if (g_strcmp0 ((char*)node->name, cmdty_slots) == 0)
166 : : {
167 : : /* We ignore the results here */
168 : 1 : dom_tree_create_instance_slots (node, QOF_INSTANCE (com));
169 : : }
170 : : else
171 : : {
172 : : struct com_char_handler* mark;
173 : :
174 : 412 : auto call_commodity_handler = [&](gnc_commodity* com, const char* txt)
175 : : {
176 : 412 : auto val = gnc_strstrip (txt);
177 : 412 : (mark->func) (com, val.c_str());
178 : 412 : };
179 : :
180 : 5022 : for (mark = com_handlers; mark->tag; mark++)
181 : : {
182 : 4344 : if (g_strcmp0 (mark->tag, (char*)node->name) == 0)
183 : : {
184 : 412 : if (apply_xmlnode_text (call_commodity_handler, com, node))
185 : 412 : break;
186 : : }
187 : : }
188 : : }
189 : 1234 : }
190 : :
191 : : static gboolean
192 : 122 : valid_commodity (gnc_commodity* com)
193 : : {
194 : 122 : if (gnc_commodity_get_namespace (com) == NULL)
195 : : {
196 : 0 : PWARN ("Invalid commodity: no namespace");
197 : 0 : return FALSE;
198 : : }
199 : 122 : if (gnc_commodity_get_mnemonic (com) == NULL)
200 : : {
201 : 0 : PWARN ("Invalid commodity: no mnemonic");
202 : 0 : return FALSE;
203 : : }
204 : 122 : if (gnc_commodity_get_fraction (com) == 0)
205 : : {
206 : 0 : PWARN ("Invalid commodity: 0 fraction");
207 : 0 : return FALSE;
208 : : }
209 : 122 : return TRUE;
210 : : }
211 : :
212 : : static gnc_commodity*
213 : 122 : gnc_commodity_find_currency (QofBook* book, xmlNodePtr tree)
214 : : {
215 : : gnc_commodity_table* table;
216 : 122 : gnc_commodity* currency = NULL;
217 : 122 : gchar* exchange = NULL, *mnemonic = NULL;
218 : : xmlNodePtr node;
219 : :
220 : 1356 : for (node = tree->xmlChildrenNode; node; node = node->next)
221 : : {
222 : 1234 : if (g_strcmp0 ((char*) node->name, cmdty_namespace) == 0)
223 : 122 : exchange = (gchar*) xmlNodeGetContent (node->xmlChildrenNode);
224 : 1234 : if (g_strcmp0 ((char*) node->name, cmdty_id) == 0)
225 : 122 : mnemonic = (gchar*) xmlNodeGetContent (node->xmlChildrenNode);
226 : : }
227 : :
228 : 122 : if (exchange
229 : 122 : && gnc_commodity_namespace_is_iso (exchange)
230 : 244 : && mnemonic)
231 : : {
232 : 19 : table = gnc_commodity_table_get_table (book);
233 : 19 : currency = gnc_commodity_table_lookup (table, exchange, mnemonic);
234 : : }
235 : :
236 : 122 : if (exchange)
237 : 122 : xmlFree (exchange);
238 : 122 : if (mnemonic)
239 : 113 : xmlFree (mnemonic);
240 : :
241 : 122 : return currency;
242 : : }
243 : :
244 : : static gboolean
245 : 701 : gnc_commodity_end_handler (gpointer data_for_children,
246 : : GSList* data_from_children, GSList* sibling_data,
247 : : gpointer parent_data, gpointer global_data,
248 : : gpointer* result, const gchar* tag)
249 : : {
250 : : gnc_commodity* com, *old_com;
251 : : xmlNodePtr achild;
252 : 701 : xmlNodePtr tree = (xmlNodePtr)data_for_children;
253 : 701 : gxpf_data* gdata = (gxpf_data*)global_data;
254 : 701 : QofBook* book = static_cast<decltype (book)> (gdata->bookdata);
255 : :
256 : 701 : if (parent_data)
257 : : {
258 : 559 : return TRUE;
259 : : }
260 : :
261 : : /* OK. For some messed up reason this is getting called again with a
262 : : NULL tag. So we ignore those cases */
263 : 142 : if (!tag)
264 : : {
265 : 20 : return TRUE;
266 : : }
267 : :
268 : 122 : g_return_val_if_fail (tree, FALSE);
269 : :
270 : 122 : com = gnc_commodity_new (book, NULL, NULL, NULL, NULL, 0);
271 : 122 : old_com = gnc_commodity_find_currency (book, tree);
272 : 122 : if (old_com)
273 : 19 : gnc_commodity_copy (com, old_com);
274 : :
275 : 1356 : for (achild = tree->xmlChildrenNode; achild; achild = achild->next)
276 : : {
277 : 1234 : set_commodity_value (achild, com);
278 : : }
279 : :
280 : 122 : if (!valid_commodity (com))
281 : : {
282 : 0 : PWARN ("Invalid commodity parsed");
283 : 0 : xmlElemDump (stdout, NULL, tree);
284 : 0 : printf ("\n");
285 : 0 : fflush (stdout);
286 : 0 : gnc_commodity_destroy (com);
287 : 0 : return FALSE;
288 : : }
289 : :
290 : 122 : gdata->cb (tag, gdata->parsedata, com);
291 : :
292 : 122 : xmlFreeNode (tree);
293 : :
294 : 122 : return TRUE;
295 : : }
296 : :
297 : :
298 : : sixtp*
299 : 64 : gnc_commodity_sixtp_parser_create (void)
300 : : {
301 : 64 : return sixtp_dom_parser_new (gnc_commodity_end_handler, NULL, NULL);
302 : : }
|