GnuCash  5.6-150-g038405b370+
gnc-commodity-xml-v2.cpp
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 gnc_commodity_dom_tree_create (const gnc_commodity* com)
60 {
61  gnc_quote_source* source;
62  const char* string;
63  xmlNodePtr ret;
64  gboolean currency = gnc_commodity_is_iso (com);
65  xmlNodePtr slotsnode =
66  qof_instance_slots_to_dom_tree (cmdty_slots, QOF_INSTANCE (com));
67 
68  if (currency && !gnc_commodity_get_quote_flag (com) && !slotsnode)
69  return NULL;
70 
71  ret = xmlNewNode (NULL, BAD_CAST gnc_commodity_string);
72 
73  xmlSetProp (ret, BAD_CAST "version", BAD_CAST commodity_version_string);
74 
75  xmlAddChild (ret, text_to_dom_tree (cmdty_namespace,
77  xmlAddChild (ret, text_to_dom_tree (cmdty_id,
79 
80  if (!currency)
81  {
83  {
84  xmlAddChild (ret, text_to_dom_tree (cmdty_name,
86  }
87 
88  const char* cusip = gnc_commodity_get_cusip (com);
89  if (cusip && *cusip)
90  {
91  xmlAddChild (ret, text_to_dom_tree (cmdty_xcode, cusip));
92  }
93 
94  xmlAddChild (ret, int_to_dom_tree (cmdty_fraction,
96  }
97 
99  {
100  xmlNewChild (ret, NULL, BAD_CAST cmdty_get_quotes, NULL);
101  source = gnc_commodity_get_quote_source (com);
102  if (source)
103  xmlAddChild (ret, text_to_dom_tree (cmdty_quote_source,
105  string = gnc_commodity_get_quote_tz (com);
106  if (string)
107  xmlAddChild (ret, text_to_dom_tree (cmdty_quote_tz, string));
108  }
109 
110  if (slotsnode)
111  xmlAddChild (ret, slotsnode);
112 
113  return ret;
114 }
115 
116 /***********************************************************************/
117 
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 set_commodity_value (xmlNodePtr node, gnc_commodity* com)
136 {
137  if (g_strcmp0 ((char*) node->name, cmdty_fraction) == 0)
138  {
139  gint64 val;
140  char* string;
141 
142  string = (char*) xmlNodeGetContent (node->xmlChildrenNode);
143  if (string_to_gint64 (string, &val))
144  {
145  gnc_commodity_set_fraction (com, val);
146  }
147  xmlFree (string);
148  }
149  else if (g_strcmp0 ((char*)node->name, cmdty_get_quotes) == 0)
150  {
151  gnc_commodity_set_quote_flag (com, TRUE);
152  }
153  else if (g_strcmp0 ((char*)node->name, cmdty_quote_source) == 0)
154  {
155  gnc_quote_source* source;
156  char* string;
157 
158  string = (char*) xmlNodeGetContent (node->xmlChildrenNode);
159  source = gnc_quote_source_lookup_by_internal (string);
160  if (!source)
161  source = gnc_quote_source_add_new (string, FALSE);
162  gnc_commodity_set_quote_source (com, source);
163  xmlFree (string);
164  }
165  else if (g_strcmp0 ((char*)node->name, cmdty_slots) == 0)
166  {
167  /* We ignore the results here */
168  dom_tree_create_instance_slots (node, QOF_INSTANCE (com));
169  }
170  else
171  {
172  struct com_char_handler* mark;
173 
174  auto call_commodity_handler = [&](gnc_commodity* com, const char* txt)
175  {
176  auto val = gnc_strstrip (txt);
177  (mark->func) (com, val.c_str());
178  };
179 
180  for (mark = com_handlers; mark->tag; mark++)
181  {
182  if (g_strcmp0 (mark->tag, (char*)node->name) == 0)
183  {
184  if (apply_xmlnode_text (call_commodity_handler, com, node))
185  break;
186  }
187  }
188  }
189 }
190 
191 static gboolean
192 valid_commodity (gnc_commodity* com)
193 {
194  if (gnc_commodity_get_namespace (com) == NULL)
195  {
196  PWARN ("Invalid commodity: no namespace");
197  return FALSE;
198  }
199  if (gnc_commodity_get_mnemonic (com) == NULL)
200  {
201  PWARN ("Invalid commodity: no mnemonic");
202  return FALSE;
203  }
204  if (gnc_commodity_get_fraction (com) == 0)
205  {
206  PWARN ("Invalid commodity: 0 fraction");
207  return FALSE;
208  }
209  return TRUE;
210 }
211 
212 static gnc_commodity*
213 gnc_commodity_find_currency (QofBook* book, xmlNodePtr tree)
214 {
215  gnc_commodity_table* table;
216  gnc_commodity* currency = NULL;
217  gchar* exchange = NULL, *mnemonic = NULL;
218  xmlNodePtr node;
219 
220  for (node = tree->xmlChildrenNode; node; node = node->next)
221  {
222  if (g_strcmp0 ((char*) node->name, cmdty_namespace) == 0)
223  exchange = (gchar*) xmlNodeGetContent (node->xmlChildrenNode);
224  if (g_strcmp0 ((char*) node->name, cmdty_id) == 0)
225  mnemonic = (gchar*) xmlNodeGetContent (node->xmlChildrenNode);
226  }
227 
228  if (exchange
229  && gnc_commodity_namespace_is_iso (exchange)
230  && mnemonic)
231  {
233  currency = gnc_commodity_table_lookup (table, exchange, mnemonic);
234  }
235 
236  if (exchange)
237  xmlFree (exchange);
238  if (mnemonic)
239  xmlFree (mnemonic);
240 
241  return currency;
242 }
243 
244 static gboolean
245 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  xmlNodePtr tree = (xmlNodePtr)data_for_children;
253  gxpf_data* gdata = (gxpf_data*)global_data;
254  QofBook* book = static_cast<decltype (book)> (gdata->bookdata);
255 
256  if (parent_data)
257  {
258  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  if (!tag)
264  {
265  return TRUE;
266  }
267 
268  g_return_val_if_fail (tree, FALSE);
269 
270  com = gnc_commodity_new (book, NULL, NULL, NULL, NULL, 0);
271  old_com = gnc_commodity_find_currency (book, tree);
272  if (old_com)
273  gnc_commodity_copy (com, old_com);
274 
275  for (achild = tree->xmlChildrenNode; achild; achild = achild->next)
276  {
277  set_commodity_value (achild, com);
278  }
279 
280  if (!valid_commodity (com))
281  {
282  PWARN ("Invalid commodity parsed");
283  xmlElemDump (stdout, NULL, tree);
284  printf ("\n");
285  fflush (stdout);
286  gnc_commodity_destroy (com);
287  return FALSE;
288  }
289 
290  gdata->cb (tag, gdata->parsedata, com);
291 
292  xmlFreeNode (tree);
293 
294  return TRUE;
295 }
296 
297 
298 sixtp*
299 gnc_commodity_sixtp_parser_create (void)
300 {
301  return sixtp_dom_parser_new (gnc_commodity_end_handler, NULL, NULL);
302 }
This is the private header for the account structure.
const char * gnc_commodity_get_cusip(const gnc_commodity *cm)
Retrieve the &#39;exchange code&#39; for the specified commodity.
gnc_commodity_table * gnc_commodity_table_get_table(QofBook *book)
Returns the commodity table associated with a book.
Definition: sixtp.h:129
int gnc_commodity_get_fraction(const gnc_commodity *cm)
Retrieve the fraction for the specified commodity.
const char * gnc_commodity_get_mnemonic(const gnc_commodity *cm)
Retrieve the mnemonic for the specified commodity.
gnc_quote_source * gnc_quote_source_add_new(const char *source_name, gboolean supported)
Create a new quote source.
gboolean gnc_commodity_get_quote_flag(const gnc_commodity *cm)
Retrieve the automatic price quote flag for the specified commodity.
void gnc_commodity_set_quote_tz(gnc_commodity *cm, const char *tz)
Set the automatic price quote timezone for the specified commodity.
const char * gnc_commodity_get_quote_tz(const gnc_commodity *cm)
Retrieve the automatic price quote timezone for the specified commodity.
void gnc_commodity_set_fraction(gnc_commodity *cm, int fraction)
Set the fraction for the specified commodity.
const char * gnc_commodity_get_namespace(const gnc_commodity *cm)
Retrieve the namespace for the specified commodity.
void gnc_commodity_set_quote_flag(gnc_commodity *cm, const gboolean flag)
Set the automatic price quote flag for the specified commodity.
#define PWARN(format, args...)
Log a warning.
Definition: qoflog.h:250
void gnc_commodity_set_quote_source(gnc_commodity *cm, gnc_quote_source *src)
Set the automatic price quote source for the specified commodity.
Account handling public routines.
void gnc_commodity_set_cusip(gnc_commodity *cm, const char *cusip)
Set the &#39;exchange code&#39; for the specified commodity.
gnc_commodity * gnc_commodity_new(QofBook *book, const char *fullname, const char *name_space, const char *mnemonic, const char *cusip, int fraction)
Create a new commodity.
gboolean gnc_commodity_namespace_is_iso(const char *name_space)
Checks to see if the specified commodity namespace is the namespace for ISO 4217 currencies.
const char * gnc_commodity_get_fullname(const gnc_commodity *cm)
Retrieve the full name for the specified commodity.
gnc_quote_source * gnc_quote_source_lookup_by_internal(const char *name)
Given the internal (gnucash or F::Q) name of a quote source, find the data structure identified by th...
void gnc_commodity_set_fullname(gnc_commodity *cm, const char *fullname)
Set the full name for the specified commodity.
gnc_quote_source * gnc_commodity_get_quote_source(const gnc_commodity *cm)
Retrieve the automatic price quote source for the specified commodity.
void gnc_commodity_set_mnemonic(gnc_commodity *cm, const char *mnemonic)
Set the mnemonic for the specified commodity.
void gnc_commodity_set_namespace(gnc_commodity *cm, const char *name_space)
Set the namespace for the specified commodity.
const char * gnc_quote_source_get_internal_name(const gnc_quote_source *source)
Given a gnc_quote_source data structure, return the internal name of this quote source.
void gnc_commodity_copy(gnc_commodity *dest, const gnc_commodity *src)
Copy src into dest.
void gnc_commodity_destroy(gnc_commodity *cm)
Destroy a commodity.
gboolean gnc_commodity_is_iso(const gnc_commodity *cm)
Checks to see if the specified commodity is an ISO 4217 recognized currency.