QOF: qsf-backend.c Source File

QOF 0.7.5

- Main Page
- Related Pages
- Modules
- Data Structures
- Files

- File List
- Globals

qsf-backend.c
1 /*******************************************************************
2 * qsf-backend.c
3 *
4 * Sat Jan 1 15:07:14 2005
5 * Copyright 2005, 2006 Neil Williams
6 * linux@codehelp.co.uk
7 *******************************************************************/
8 /*
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 */
23
24 #include "config.h"
25 #include <errno.h>
26 #include <sys/stat.h>
27 #include <glib.h>
28 #include <libxml/xmlmemory.h>
29 #include <libxml/tree.h>
30 #include <libxml/parser.h>
31 #include <libxml/xmlschemas.h>
32 #include "qof.h"
33 #include "qofobject-p.h"
34 #include "qof-backend-qsf.h"
35 #include "qsf-xml.h"
36 #include "qsf-dir.h"
37
38 #define QSF_TYPE_BINARY "binary"
39 #define QSF_TYPE_GLIST "glist"
40 #define QSF_TYPE_FRAME "frame"
41
42 static QofLogModule log_module = QOF_MOD_QSF;
43
44 static void qsf_object_commitCB (gpointer key, gpointer value,
45 gpointer data);
46
47 struct QSFBackend_s
48 {
49 QofBackend be;
50 QsfParam *params;
51 gchar *fullpath;
52 };
53
54 typedef struct QSFBackend_s QSFBackend;
55
56 static void
57 option_cb (QofBackendOption * option, gpointer data)
58 {
59 QsfParam *params;
60
61 params = (QsfParam *) data;
62 g_return_if_fail (params);
63 if (0 == safe_strcmp (QSF_COMPRESS, option->option_name))
64 {
65 params->use_gz_level = (*(gint64 *) option->value);
66 PINFO (" compression=%" G_GINT64_FORMAT, params->use_gz_level);
67 }
68 if (0 == safe_strcmp (QSF_MAP_FILES, option->option_name))
69 {
70 params->map_files = g_list_copy ((GList *) option->value);
71 }
72 if (0 == safe_strcmp (QSF_ENCODING, option->option_name))
73 {
74 params->encoding = g_strdup (option->value);
75 PINFO (" encoding=%s", params->encoding);
76 }
77 if (0 == safe_strcmp (QSF_DATE_CONVERT, option->option_name))
78 {
79 params->convert = (*(double *) option->value);
80 if (params->convert > 0)
81 PINFO (" converting date into time on file write.");
82 }
83 }
84
85 static void
86 qsf_load_config (QofBackend * be, KvpFrame * config)
87 {
88 QSFBackend *qsf_be;
89 QsfParam *params;
90
91 ENTER (" ");
92 qsf_be = (QSFBackend *) be;
93 g_return_if_fail (qsf_be->params);
94 params = qsf_be->params;
95 qof_backend_option_foreach (config, option_cb, params);
96 LEAVE (" ");
97 }
98
99 static KvpFrame *
100 qsf_get_config (QofBackend * be)
101 {
102 QofBackendOption *option;
103 QSFBackend *qsf_be;
104 QsfParam *params;
105
106 if (!be)
107 {
108 return NULL;
109 }
110 ENTER (" ");
111 qsf_be = (QSFBackend *) be;
112 g_return_val_if_fail (qsf_be->params, NULL);
113 params = qsf_be->params;
114 qof_backend_prepare_frame (be);
115 option = g_new0 (QofBackendOption, 1);
116 option->option_name = QSF_COMPRESS;
117 option->description =
118 _("Level of compression to use: 0 for none, 9 for highest.");
119 option->tooltip =
120 _("QOF can compress QSF XML files using gzip. "
121 "Note that compression is not used when outputting to STDOUT.");
122 option->type = KVP_TYPE_GINT64;
123 /* GINT_TO_POINTER can only be used for 32bit values. */
124 option->value = (gpointer) & params->use_gz_level;
125 qof_backend_prepare_option (be, option);
126 g_free (option);
127 option = g_new0 (QofBackendOption, 1);
128 option->option_name = QSF_MAP_FILES;
129 option->description =
130 _("List of QSF map files to use for this session.");
131 option->tooltip =
132 _("QOF can convert objects within QSF XML files "
133 "using a map of the changes required.");
134 option->type = KVP_TYPE_GLIST;
135 option->value = (gpointer) params->map_files;
136 qof_backend_prepare_option (be, option);
137 g_free (option);
138 option = g_new0 (QofBackendOption, 1);
139 option->option_name = QSF_ENCODING;
140 option->description =
141 _("Encoding string to use when writing the XML file.");
142 option->tooltip =
143 _("QSF defaults to UTF-8. Other encodings are supported by "
144 "passing the encoding string in this option.");
145 option->type = KVP_TYPE_STRING;
146 option->value = (gpointer) params->encoding;
147 qof_backend_prepare_option (be, option);
148 g_free (option);
149 option = g_new0 (QofBackendOption, 1);
150 option->option_name = QSF_DATE_CONVERT;
151 option->description =
152 _("Convert deprecated date values to time values.");
153 option->tooltip =
154 _("Applications that support the new QOF time format "
155 "need to enable this option to convert older date values into time. "
156 "Applications that still use date should not set this option "
157 "until time values are supported.");
158 option->type = KVP_TYPE_GINT64;
159 option->value = &params->convert;
160 qof_backend_prepare_option (be, option);
161 g_free (option);
162 LEAVE (" ");
163 return qof_backend_complete_frame (be);
164 }
165
166 GList **
167 qsf_map_prepare_list (GList ** maps)
168 {
169 /* Add new map filenames here. */
171 *maps = g_list_prepend (*maps, "pilot-qsf-GnuCashInvoice.xml");
172 *maps = g_list_prepend (*maps, "pilot-qsf-gncCustomer.xml");
173 return maps;
174 }
175
176 static void
177 qsf_param_init (QsfParam * params)
178 {
179 gchar *qsf_time_string;
180 gchar *qsf_enquiry_date;
181 gchar *qsf_time_now;
182 gchar *qsf_time_precision;
183
184 g_return_if_fail (params != NULL);
185 params->count = 0;
186 params->convert = 1;
187 params->use_gz_level = 0;
188 params->supported_types = NULL;
189 params->file_type = QSF_UNDEF;
190 params->qsf_ns = NULL;
191 params->output_doc = NULL;
192 params->output_node = NULL;
193 params->lister = NULL;
194 params->full_kvp_path = NULL;
195 params->map_ns = NULL;
196 params->map_files = NULL;
197 params->map_path = NULL;
198 params->encoding = "UTF-8";
199 params->qsf_object_list = NULL;
200 params->qsf_parameter_hash =
201 g_hash_table_new (g_str_hash, g_str_equal);
202 params->qsf_default_hash = g_hash_table_new (g_str_hash, g_str_equal);
203 params->qsf_define_hash = g_hash_table_new (g_str_hash, g_str_equal);
204 params->qsf_calculate_hash =
205 g_hash_table_new (g_str_hash, g_str_equal);
206 params->referenceList = NULL;
207 params->supported_types =
208 g_slist_append (params->supported_types, QOF_TYPE_STRING);
209 params->supported_types =
210 g_slist_append (params->supported_types, QOF_TYPE_GUID);
211 params->supported_types =
212 g_slist_append (params->supported_types, QOF_TYPE_BOOLEAN);
213 params->supported_types =
214 g_slist_append (params->supported_types, QOF_TYPE_NUMERIC);
215 #ifndef QOF_DISABLE_DEPRECATED
216 /* Support read if built with deprecated code included.
217 Support write only if convert option is not enabled. */
218 params->supported_types =
219 g_slist_append (params->supported_types, QOF_TYPE_DATE);
220 #endif
221 params->supported_types =
222 g_slist_append (params->supported_types, QOF_TYPE_TIME);
223 params->supported_types =
224 g_slist_append (params->supported_types, QOF_TYPE_INT32);
225 params->supported_types =
226 g_slist_append (params->supported_types, QOF_TYPE_INT64);
227 params->supported_types =
228 g_slist_append (params->supported_types, QOF_TYPE_DOUBLE);
229 params->supported_types =
230 g_slist_append (params->supported_types, QOF_TYPE_CHAR);
231 params->supported_types =
232 g_slist_append (params->supported_types, QOF_TYPE_KVP);
233 params->supported_types =
234 g_slist_append (params->supported_types, QOF_TYPE_COLLECT);
235 params->supported_types =
236 g_slist_append (params->supported_types, QOF_TYPE_CHOICE);
237 qsf_time_precision = "%j";
238 qsf_enquiry_date = qof_time_stamp_now ();
239 qsf_time_string = qof_date_print (qof_date_get_current(),
240 QOF_DATE_FORMAT_ISO);
241 qsf_time_now = qof_time_stamp_now ();
242
243 g_hash_table_insert (params->qsf_default_hash, "qsf_enquiry_date",
244 qsf_enquiry_date);
245 g_hash_table_insert (params->qsf_default_hash, "qsf_time_now",
246 qof_time_get_current());
247 g_hash_table_insert (params->qsf_default_hash, "qsf_time_string",
248 qsf_time_string);
249 /* default map files */
250 params->map_files = *qsf_map_prepare_list (&params->map_files);
251 params->err_nomap = qof_error_register
252 (_("The selected QSF Object file '%s' requires a "
253 "map but it was not provided."), TRUE);
254 params->err_overflow = qof_error_register
255 (_("When converting XML strings into numbers, an "
256 "overflow has been detected. The QSF object file "
257 "'%s' contains invalid data in a field that is "
258 "meant to hold a number."), TRUE);
259 }
260
261 static gboolean
262 qsf_determine_file_type (const gchar * path)
263 {
264 struct stat sbuf;
265
266 if (!path)
267 return TRUE;
268 if (0 == safe_strcmp (path, QOF_STDOUT))
269 return TRUE;
270 if (stat (path, &sbuf) < 0)
271 {
272 /* in case the error is that the file does not exist */
273 FILE * f;
274 f = fopen (path, "a+");
275 if (f)
276 {
277 fclose (f);
278 return TRUE;
279 }
280 return FALSE;
281 }
282 if (sbuf.st_size == 0)
283 return TRUE;
284 if (is_our_qsf_object (path))
285 return TRUE;
286 else if (is_qsf_object (path))
287 return TRUE;
288 else if (is_qsf_map (path))
289 return TRUE;
290 return FALSE;
291 }
292
293 static void
294 qsf_session_begin (QofBackend * be, QofSession * session,
295 const gchar * book_path, gboolean ignore_lock,
296 gboolean create_if_nonexistent)
297 {
298 QSFBackend *qsf_be;
299 gchar *p, *path;
300
301 PINFO (" ignore_lock=%d create_if_nonexistent=%d", ignore_lock,
302 create_if_nonexistent);
303 g_return_if_fail (be != NULL);
304 g_return_if_fail (session);
305 be->fullpath = g_strdup (book_path);
306 qsf_be = (QSFBackend *) be;
307 g_return_if_fail (qsf_be->params != NULL);
308 qsf_be->fullpath = NULL;
309 if (book_path == NULL)
310 {
311 /* allow use of stdout */
312 qof_error_set_be (be, QOF_SUCCESS);
313 return;
314 }
315 p = strchr (book_path, ':');
316 if (p)
317 {
318 path = g_strdup (book_path);
319 if (!g_ascii_strncasecmp (path, "file:", 5))
320 {
321 p = g_new0 (gchar, strlen (path) - 5 + 1);
322 strcpy (p, path + 5);
323 }
324 qsf_be->fullpath = g_strdup (p);
325 g_free (path);
326 }
327 else
328 qsf_be->fullpath = g_strdup (book_path);
329 if (create_if_nonexistent)
330 {
331 FILE *f;
332
333 f = fopen (qsf_be->fullpath, "a+");
334 if (f)
335 fclose (f);
336 else
337 {
338 qof_error_set_be (be, qof_error_register
339 (_("could not write to '%s'. "
340 "That database may be on a read-only file system, "
341 "or you may not have write permission for the "
342 "directory.\n"), TRUE));
343 return;
344 }
345 }
346 qof_error_set_be (be, QOF_SUCCESS);
347 }
348
349 static void
350 qsf_free_params (QsfParam * params)
351 {
352 g_hash_table_destroy (params->qsf_calculate_hash);
353 g_hash_table_destroy (params->qsf_default_hash);
354 if (params->referenceList)
355 g_list_free (params->referenceList);
356 g_slist_free (params->supported_types);
357 if (params->map_ns)
358 xmlFreeNs (params->map_ns);
359 if (params->output_doc)
360 xmlFreeDoc (params->output_doc);
361 }
362
363 static void
364 qsf_session_end (QofBackend * be)
365 {
366 QSFBackend *qsf_be;
367
368 qsf_be = (QSFBackend *) be;
369 g_return_if_fail (qsf_be != NULL);
370 qsf_free_params (qsf_be->params);
371 g_free (qsf_be->fullpath);
372 qsf_be->fullpath = NULL;
373 xmlCleanupParser ();
374 }
375
376 static void
377 qsf_destroy_backend (QofBackend * be)
378 {
379 g_free (be);
380 }
381
382 static void
383 ent_ref_cb (QofEntity * ent, gpointer user_data)
384 {
385 QsfParam *params;
386 QofEntityReference *ref;
387 void (*reference_setter) (QofEntity *, QofEntity *);
388 QofEntity *reference;
389 QofCollection *coll;
390 QofIdType type;
391
392 params = (QsfParam *) user_data;
393 g_return_if_fail (params);
394 while (params->referenceList)
395 {
396 ref = (QofEntityReference *) params->referenceList->data;
397 if (qof_object_is_choice (ent->e_type))
398 type = ref->choice_type;
399 else
400 type = ref->type;
401 coll = qof_book_get_collection (params->book, type);
402 reference = qof_collection_lookup_entity (coll, ref->ref_guid);
403 reference_setter =
404 (void (*)(QofEntity *, QofEntity *)) ref->param->param_setfcn;
405 if (reference_setter != NULL)
406 {
407 qof_util_param_edit ((QofInstance *) ent, ref->param);
408 qof_util_param_edit ((QofInstance *) reference, ref->param);
409 reference_setter (ent, reference);
410 qof_util_param_commit ((QofInstance *) ent, ref->param);
411 qof_util_param_commit ((QofInstance *) reference, ref->param);
412 }
413 params->referenceList = g_list_next (params->referenceList);
414 }
415 }
416
417 static void
418 insert_ref_cb (QofObject * obj, gpointer user_data)
419 {
420 QsfParam *params;
421
422 params = (QsfParam *) user_data;
423 g_return_if_fail (params);
424 qof_object_foreach (obj->e_type, params->book, ent_ref_cb, params);
425 }
426
427 /*================================================
428 Load QofEntity into QofBook from XML in memory
429 ==================================================*/
430
431 static gboolean
432 qsfdoc_to_qofbook (QsfParam * params)
433 {
434 QofInstance *inst;
435 struct QsfNodeIterate qiter;
436 QofBook *book;
437 GList *object_list;
438 xmlNodePtr qsf_root;
439 xmlNsPtr qsf_ns;
440
441 g_return_val_if_fail (params != NULL, FALSE);
442 g_return_val_if_fail (params->input_doc != NULL, FALSE);
443 g_return_val_if_fail (params->book != NULL, FALSE);
444 g_return_val_if_fail (params->file_type == OUR_QSF_OBJ, FALSE);
445 qsf_root = xmlDocGetRootElement (params->input_doc);
446 if (!qsf_root)
447 return FALSE;
448 qsf_ns = qsf_root->ns;
449 qiter.ns = qsf_ns;
450 book = params->book;
451 params->referenceList =
452 (GList *) qof_book_get_data (book, ENTITYREFERENCE);
453 qsf_node_foreach (qsf_root, qsf_book_node_handler, &qiter, params);
454 object_list = g_list_copy (params->qsf_object_list);
455 while (object_list != NULL)
456 {
457 params->object_set = object_list->data;
458 object_list = g_list_next (object_list);
459 params->qsf_parameter_hash = params->object_set->parameters;
460 if (!qof_class_is_registered (params->object_set->object_type))
461 continue;
462 inst =
463 (QofInstance *) qof_object_new_instance (params->object_set->
464 object_type, book);
465 g_return_val_if_fail (inst != NULL, FALSE);
466 params->qsf_ent = &inst->entity;
467 g_hash_table_foreach (params->qsf_parameter_hash,
468 qsf_object_commitCB, params);
469 }
470 qof_object_foreach_type (insert_ref_cb, params);
471 qof_book_set_data (book, ENTITYREFERENCE, params->referenceList);
472 return TRUE;
473 }
474
475 /* QofBackend routine to load from file - needs a map.
476 */
477 static gboolean
478 load_qsf_object (QofBook * book, const gchar * fullpath,
479 QsfParam * params)
480 {
481 xmlNodePtr qsf_root, map_root;
482 xmlDocPtr mapDoc, foreign_doc;
483 gchar *map_path, *map_file;
484
485 map_file = params->map_path;
486 mapDoc = NULL;
487 /* use selected map */
488 if (!map_file)
489 {
490 qof_error_set_be (params->be, params->err_nomap);
491 return FALSE;
492 }
493 foreign_doc = xmlParseFile (fullpath);
494 if (foreign_doc == NULL)
495 {
496 qof_error_set_be (params->be, qof_error_register
497 (_("There was an error parsing the file '%s'.\n"), TRUE));
498 return FALSE;
499 }
500 qsf_root = NULL;
501 qsf_root = xmlDocGetRootElement (foreign_doc);
502 params->qsf_ns = qsf_root->ns;
503 params->book = book;
504 map_path = g_strdup_printf ("%s/%s", QSF_SCHEMA_DIR, map_file);
505 if (!map_path)
506 {
507 qof_error_set_be (params->be, params->err_nomap);
508 return FALSE;
509 }
510 mapDoc = xmlParseFile (map_path);
511 if (!mapDoc)
512 {
513 qof_error_set_be (params->be, params->err_nomap);
514 return FALSE;
515 }
516 map_root = xmlDocGetRootElement (mapDoc);
517 params->map_ns = map_root->ns;
518 params->input_doc = qsf_object_convert (mapDoc, qsf_root, params);
519 qsfdoc_to_qofbook (params);
520 return TRUE;
521 }
522
523 static gboolean
524 load_our_qsf_object (const gchar * fullpath, QsfParam * params)
525 {
526 xmlNodePtr qsf_root;
527
528 params->input_doc = xmlParseFile (fullpath);
529 if (params->input_doc == NULL)
530 {
531 qof_error_set_be (params->be, qof_error_register
532 (_("There was an error parsing the file '%s'."), TRUE));
533 return FALSE;
534 }
535 qsf_root = NULL;
536 qsf_root = xmlDocGetRootElement (params->input_doc);
537 params->qsf_ns = qsf_root->ns;
538 return qsfdoc_to_qofbook (params);
539 }
540
541 /* Determine the type of QSF and load it into the QofBook
542
543 - is_our_qsf_object, OUR_QSF_OBJ, QSF object file using only QOF objects known
544 to the calling process. No map is required.
545 - is_qsf_object, IS_QSF_OBJ, QSF object file that may or may not have a QSF map
546 to convert external objects. This temporary type will be set to HAVE_QSF_MAP
547 if a suitable map exists, or an error value returned: ERR_QSF_NO_MAP,
548 ERR_QSF_BAD_MAP or ERR_QSF_WRONG_MAP. This allows the calling process to inform
549 the user that the QSF itself is valid but a suitable map cannot be found.
550 - is_qsf_map, IS_QSF_MAP, QSF map file. In the backend, this generates
551 ERR_QSF_MAP_NOT_OBJ but it can be used internally when processing maps to
552 match a QSF object.
553
554 returns NULL on error, otherwise a pointer to the QofBook. Use
555 the qof_book_merge API to merge the new data into the current
556 QofBook.
557 */
558 static void
559 qsf_file_type (QofBackend * be, QofBook * book)
560 {
561 QSFBackend *qsf_be;
562 QofErrorId parse_err;
563 QsfParam *params;
564 FILE *f;
565 gchar *path;
566 gboolean result;
567
568 g_return_if_fail (be != NULL);
569 g_return_if_fail (book != NULL);
570 qsf_be = (QSFBackend *) be;
571 g_return_if_fail (qsf_be != NULL);
572 g_return_if_fail (qsf_be->fullpath != NULL);
573 g_return_if_fail (qsf_be->params != NULL);
574 parse_err = qof_error_register
575 (_("There was an error parsing the file '%s'."), TRUE);
576 params = qsf_be->params;
577 params->book = book;
578 DEBUG (" qsf_be->fullpath=%s", qsf_be->fullpath);
579 path = g_strdup (qsf_be->fullpath);
580 f = fopen (path, "r");
581 if (!f)
582 qof_error_set_be (be, qof_error_register
583 (_("There was an error reading the file '%s'."), TRUE));
584 else
585 fclose (f);
586 params->filepath = g_strdup (path);
587 result = is_our_qsf_object_be (params);
588 if (result)
589 {
590 params->file_type = OUR_QSF_OBJ;
591 result = load_our_qsf_object (path, params);
592 if (!result)
593 qof_error_set_be (be, parse_err);
594 return;
595 }
596 else if (is_qsf_object_be (params))
597 {
598 params->file_type = IS_QSF_OBJ;
599 result = load_qsf_object (book, path, params);
600 if (!result)
601 qof_error_set_be (be, parse_err);
602 return;
603 }
604 if (qof_error_check_be (be) == params->err_nomap)
605 {
606 /* usable QSF object but no map available */
607 params->file_type = IS_QSF_OBJ;
608 result = TRUE;
609 }
610 if (result == FALSE)
611 {
612 if (is_qsf_map_be (params))
613 {
614 params->file_type = IS_QSF_MAP;
615 qof_error_set_be (be, qof_error_register
616 (_("The selected file '%s' is a QSF map and cannot "
617 "be opened as a QSF object."), TRUE));
618 }
619 }
620 }
621
622 static void
623 qsf_object_sequence (QofParam * qof_param, gpointer data)
624 {
625 QsfParam *params;
626 GSList *checklist, *result;
627
628 g_return_if_fail (data != NULL);
629 params = (QsfParam *) data;
630 result = NULL;
631 checklist = NULL;
632 params->knowntype = FALSE;
633 checklist = g_slist_copy (params->supported_types);
634 for (result = checklist; result != NULL; result = result->next)
635 {
636 if (0 ==
637 safe_strcmp ((QofIdType) result->data,
638 qof_param->param_type))
639 params->knowntype = TRUE;
640 }
641 g_slist_free (checklist);
642 if (0 == safe_strcmp (qof_param->param_type, params->qof_type))
643 {
644 params->qsf_sequence =
645 g_slist_append (params->qsf_sequence, qof_param);
646 params->knowntype = TRUE;
647 }
648 /* handle params->qof_type = QOF_TYPE_GUID and qof_param->param_type != known type */
649 if (0 == safe_strcmp (params->qof_type, QOF_TYPE_GUID)
650 && (params->knowntype == FALSE))
651 {
652 params->qsf_sequence =
653 g_slist_append (params->qsf_sequence, qof_param);
654 params->knowntype = TRUE;
655 }
656 }
657
658 /* receives each entry from supported_types in sequence
659 type = qof data type from supported list
660 user_data = params. Holds object type
661 */
662 static void
663 qsf_supported_parameters (gpointer type, gpointer user_data)
664 {
665 QsfParam *params;
666
667 g_return_if_fail (user_data != NULL);
668 params = (QsfParam *) user_data;
669 params->qof_type = (QofIdType) type;
670 params->knowntype = FALSE;
671 qof_class_param_foreach (params->qof_obj_type, qsf_object_sequence,
672 params);
673 }
674
675 static KvpValueType
676 qsf_to_kvp_helper (const char *type_string)
677 {
678 if (0 == safe_strcmp (QOF_TYPE_INT64, type_string))
679 return KVP_TYPE_GINT64;
680 if (0 == safe_strcmp (QOF_TYPE_DOUBLE, type_string))
681 return KVP_TYPE_DOUBLE;
682 if (0 == safe_strcmp (QOF_TYPE_NUMERIC, type_string))
683 return KVP_TYPE_NUMERIC;
684 if (0 == safe_strcmp (QOF_TYPE_STRING, type_string))
685 return KVP_TYPE_STRING;
686 if (0 == safe_strcmp (QOF_TYPE_GUID, type_string))
687 return KVP_TYPE_GUID;
688 #ifndef QOF_DISABLE_DEPRECATED
689 if (0 == safe_strcmp (QOF_TYPE_DATE, type_string))
690 return KVP_TYPE_TIMESPEC;
691 #endif
692 if (0 == safe_strcmp (QOF_TYPE_TIME, type_string))
693 return KVP_TYPE_TIME;
694 if (0 == safe_strcmp (QSF_TYPE_BINARY, type_string))
695 return KVP_TYPE_BINARY;
696 if (0 == safe_strcmp (QSF_TYPE_GLIST, type_string))
697 return KVP_TYPE_GLIST;
698 if (0 == safe_strcmp (QSF_TYPE_FRAME, type_string))
699 return KVP_TYPE_FRAME;
700 return 0;
701 }
702
703 static QofIdTypeConst
704 kvp_value_to_qof_type_helper (KvpValueType n)
705 {
706 switch (n)
707 {
708 case KVP_TYPE_GINT64:
709 {
710 return QOF_TYPE_INT64;
711 break;
712 }
713 case KVP_TYPE_DOUBLE:
714 {
715 return QOF_TYPE_DOUBLE;
716 break;
717 }
718 case KVP_TYPE_NUMERIC:
719 {
720 return QOF_TYPE_NUMERIC;
721 break;
722 }
723 case KVP_TYPE_STRING:
724 {
725 return QOF_TYPE_STRING;
726 break;
727 }
728 case KVP_TYPE_GUID:
729 {
730 return QOF_TYPE_GUID;
731 break;
732 }
733 #ifndef QOF_DISABLE_DEPRECATED
734 case KVP_TYPE_TIMESPEC:
735 {
736 return QOF_TYPE_DATE;
737 break;
738 }
739 #endif
740 case KVP_TYPE_BOOLEAN :
741 {
742 return QOF_TYPE_BOOLEAN;
743 break;
744 }
745 case KVP_TYPE_TIME :
746 {
747 return QOF_TYPE_TIME;
748 break;
749 }
750 case KVP_TYPE_BINARY:
751 {
752 return QSF_TYPE_BINARY;
753 break;
754 }
755 case KVP_TYPE_GLIST:
756 {
757 return QSF_TYPE_GLIST;
758 break;
759 }
760 case KVP_TYPE_FRAME:
761 {
762 return QSF_TYPE_FRAME;
763 break;
764 }
765 default:
766 {
767 return NULL;
768 }
769 }
770 }
771
772
773 static void
774 qsf_from_kvp_helper (const gchar * path, KvpValue * content,
775 gpointer data)
776 {
777 QsfParam *params;
778 QofParam *qof_param;
779 xmlNodePtr node;
780 KvpValueType n;
781 gchar *full_path;
782
783 params = (QsfParam *) data;
784 qof_param = params->qof_param;
785 full_path = NULL;
786 g_return_if_fail (params && path && content);
787 n = kvp_value_get_type (content);
788 switch (n)
789 {
790 case KVP_TYPE_GINT64:
791 case KVP_TYPE_DOUBLE:
792 case KVP_TYPE_NUMERIC:
793 case KVP_TYPE_STRING:
794 case KVP_TYPE_GUID:
795 case KVP_TYPE_TIME :
796 case KVP_TYPE_BOOLEAN :
797 #ifndef QOF_DISABLE_DEPRECATED
798 case KVP_TYPE_TIMESPEC:
799 #endif
800 case KVP_TYPE_BINARY:
801 case KVP_TYPE_GLIST:
802 {
803 node =
804 xmlAddChild (params->output_node,
805 xmlNewNode (params->qsf_ns,
806 BAD_CAST qof_param->param_type));
807 xmlNodeAddContent (node,
808 BAD_CAST kvp_value_to_bare_string (content));
809 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE,
810 BAD_CAST qof_param->param_name);
811 full_path =
812 g_strconcat (params->full_kvp_path, "/", path, NULL);
813 xmlNewProp (node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST full_path);
814 xmlNewProp (node, BAD_CAST QSF_OBJECT_VALUE,
815 BAD_CAST kvp_value_to_qof_type_helper (n));
816 break;
817 }
818 case KVP_TYPE_FRAME:
819 {
820 if (!params->full_kvp_path)
821 params->full_kvp_path = g_strdup (path);
822 else
823 params->full_kvp_path = g_strconcat (params->full_kvp_path,
824 "/", path, NULL);
825 kvp_frame_for_each_slot (kvp_value_get_frame (content),
826 qsf_from_kvp_helper, params);
827 g_free (params->full_kvp_path);
828 params->full_kvp_path = NULL;
829 break;
830 }
831 default:
832 {
833 PERR (" unsupported value = %d", kvp_value_get_type (content));
834 break;
835 }
836 }
837 }
838
839 static void
840 qsf_from_coll_cb (QofEntity * ent, gpointer user_data)
841 {
842 QsfParam *params;
843 QofParam *qof_param;
844 xmlNodePtr node;
845 gchar qsf_guid[GUID_ENCODING_LENGTH + 1];
846
847 params = (QsfParam *) user_data;
848 if (!ent || !params)
849 return;
850 qof_param = params->qof_param;
851 guid_to_string_buff (qof_entity_get_guid (ent), qsf_guid);
852 node = xmlAddChild (params->output_node, xmlNewNode (params->qsf_ns,
853 BAD_CAST qof_param->param_type));
854 xmlNodeAddContent (node, BAD_CAST qsf_guid);
855 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE,
856 BAD_CAST qof_param->param_name);
857 }
858
859 /******* reference handling ***********/
860
861 static gint
862 qof_reference_list_cb (gconstpointer a, gconstpointer b)
863 {
864 const QofEntityReference *aa;
865 const QofEntityReference *bb;
866
867 aa = (QofEntityReference *) a;
868 bb = (QofEntityReference *) b;
869 if (aa == NULL)
870 return 1;
871 g_return_val_if_fail ((bb != NULL), 1);
872 g_return_val_if_fail ((aa->type != NULL), 1);
873 if ((0 == guid_compare (bb->ent_guid, aa->ent_guid))
874 && (0 == safe_strcmp (bb->type, aa->type))
875 && (0 == safe_strcmp (bb->param->param_name,
876 aa->param->param_name)))
877 return 0;
878 return 1;
879 }
880
881 static QofEntityReference *
882 qof_reference_lookup (GList * referenceList, QofEntityReference * find)
883 {
884 GList *single_ref;
885 QofEntityReference *ent_ref;
886
887 if (referenceList == NULL)
888 return NULL;
889 g_return_val_if_fail (find != NULL, NULL);
890 single_ref = NULL;
891 ent_ref = NULL;
892 single_ref =
893 g_list_find_custom (referenceList, find, qof_reference_list_cb);
894 if (single_ref == NULL)
895 return ent_ref;
896 ent_ref = (QofEntityReference *) single_ref->data;
897 g_list_free (single_ref);
898 return ent_ref;
899 }
900
901 static void
902 reference_list_lookup (gpointer data, gpointer user_data)
903 {
904 QofEntity *ent;
905 QofParam *ref_param;
906 QofEntityReference *reference, *starter;
907 QsfParam *params;
908 const GUID *guid;
909 xmlNodePtr node, object_node;
910 xmlNsPtr ns;
911 GList *copy_list;
912 gchar qsf_guid[GUID_ENCODING_LENGTH + 1], *ref_name;
913
914 params = (QsfParam *) user_data;
915 ref_param = (QofParam *) data;
916 object_node = params->output_node;
917 ent = params->qsf_ent;
918 ns = params->qsf_ns;
919 starter = g_new0 (QofEntityReference, 1);
920 starter->ent_guid = qof_entity_get_guid (ent);
921 starter->type = g_strdup (ent->e_type);
922 starter->param = ref_param;
923 starter->ref_guid = NULL;
924 copy_list = g_list_copy (params->referenceList);
925 reference = qof_reference_lookup (copy_list, starter);
926 g_free (starter);
927 if (reference != NULL)
928 {
929 if ((ref_param->param_getfcn == NULL)
930 || (ref_param->param_setfcn == NULL))
931 return;
932 ref_name = g_strdup (reference->param->param_name);
933 node =
934 xmlAddChild (object_node,
935 xmlNewNode (ns, BAD_CAST QOF_TYPE_GUID));
936 guid_to_string_buff (reference->ref_guid, qsf_guid);
937 xmlNodeAddContent (node, BAD_CAST qsf_guid);
938 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST ref_name);
939 g_free (ref_name);
940 }
941 else
942 {
943 ent = (QofEntity *) ref_param->param_getfcn (ent, ref_param);
944 if (!ent)
945 return;
946 if ((0 == safe_strcmp (ref_param->param_type, QOF_TYPE_COLLECT)) ||
947 (0 == safe_strcmp (ref_param->param_type, QOF_TYPE_CHOICE)))
948 return;
949 node =
950 xmlAddChild (object_node,
951 xmlNewNode (ns, BAD_CAST QOF_TYPE_GUID));
952 guid = qof_entity_get_guid (ent);
953 guid_to_string_buff (guid, qsf_guid);
954 xmlNodeAddContent (node, BAD_CAST qsf_guid);
955 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE,
956 BAD_CAST ref_param->param_name);
957 }
958 }
959
960 /*=====================================
961 Convert QofEntity to QSF XML node
962 qof_param holds the parameter sequence.
963 =======================================*/
964 static void
965 qsf_entity_foreach (QofEntity * ent, gpointer data)
966 {
967 QsfParam *params;
968 GSList *param_list, *supported;
969 GList *ref;
970 xmlNodePtr node, object_node;
971 xmlNsPtr ns;
972 gchar *string_buffer;
973 QofParam *qof_param;
974 QofEntity *choice_ent;
975 KvpFrame *qsf_kvp;
976 QofCollection *qsf_coll;
977 gint param_count;
978 gboolean own_guid;
979 const GUID *cm_guid;
980 gchar cm_sa[GUID_ENCODING_LENGTH + 1];
981
982 g_return_if_fail (data != NULL);
983 params = (QsfParam *) data;
984 param_count = ++params->count;
985 ns = params->qsf_ns;
986 qsf_kvp = NULL;
987 own_guid = FALSE;
988 choice_ent = NULL;
989 object_node = xmlNewChild (params->book_node, params->qsf_ns,
990 BAD_CAST QSF_OBJECT_TAG, NULL);
991 xmlNewProp (object_node, BAD_CAST QSF_OBJECT_TYPE,
992 BAD_CAST ent->e_type);
993 string_buffer = g_strdup_printf ("%i", param_count);
994 xmlNewProp (object_node, BAD_CAST QSF_OBJECT_COUNT,
995 BAD_CAST string_buffer);
996 g_free (string_buffer);
997 param_list = g_slist_copy (params->qsf_sequence);
998 while (param_list != NULL)
999 {
1000 qof_param = (QofParam *) param_list->data;
1001 g_return_if_fail (qof_param != NULL);
1002 if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_GUID))
1003 {
1004 if (!own_guid)
1005 {
1006 cm_guid = qof_entity_get_guid (ent);
1007 node = xmlAddChild (object_node, xmlNewNode (ns, BAD_CAST
1008 QOF_TYPE_GUID));
1009 guid_to_string_buff (cm_guid, cm_sa);
1010 string_buffer = g_strdup (cm_sa);
1011 xmlNodeAddContent (node, BAD_CAST string_buffer);
1012 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
1013 QOF_PARAM_GUID);
1014 g_free (string_buffer);
1015 own_guid = TRUE;
1016 }
1017 params->qsf_ent = ent;
1018 params->output_node = object_node;
1019 ref = qof_class_get_referenceList (ent->e_type);
1020 if (ref != NULL)
1021 g_list_foreach (ref, reference_list_lookup, params);
1022 }
1023 if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_COLLECT))
1024 {
1025 qsf_coll = qof_param->param_getfcn (ent, qof_param);
1026 if (qsf_coll)
1027 {
1028 params->qof_param = qof_param;
1029 params->output_node = object_node;
1030 if (qof_collection_count (qsf_coll) > 0)
1031 qof_collection_foreach (qsf_coll, qsf_from_coll_cb,
1032 params);
1033 }
1034 param_list = g_slist_next (param_list);
1035 continue;
1036 }
1037 if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_CHOICE))
1038 {
1040 choice_ent =
1041 (QofEntity *) qof_param->param_getfcn (ent, qof_param);
1042 if (!choice_ent)
1043 {
1044 param_list = g_slist_next (param_list);
1045 continue;
1046 }
1047 node = xmlAddChild (object_node, xmlNewNode (ns, BAD_CAST
1048 qof_param->param_type));
1049 cm_guid = qof_entity_get_guid (choice_ent);
1050 guid_to_string_buff (cm_guid, cm_sa);
1051 string_buffer = g_strdup (cm_sa);
1052 xmlNodeAddContent (node, BAD_CAST string_buffer);
1053 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
1054 qof_param->param_name);
1055 xmlNewProp (node, BAD_CAST "name",
1056 BAD_CAST choice_ent->e_type);
1057 g_free (string_buffer);
1058 param_list = g_slist_next (param_list);
1059 continue;
1060 }
1061 if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_KVP))
1062 {
1063 qsf_kvp =
1064 (KvpFrame *) qof_param->param_getfcn (ent, qof_param);
1065 if (kvp_frame_is_empty (qsf_kvp))
1066 return;
1067 params->qof_param = qof_param;
1068 params->output_node = object_node;
1069 kvp_frame_for_each_slot (qsf_kvp, qsf_from_kvp_helper, params);
1070 }
1071 if ((qof_param->param_setfcn != NULL)
1072 && (qof_param->param_getfcn != NULL))
1073 {
1074 for (supported = g_slist_copy (params->supported_types);
1075 supported != NULL; supported = g_slist_next (supported))
1076 {
1077 if (0 == safe_strcmp ((const gchar *) supported->data,
1078 (const gchar *) qof_param->param_type))
1079 {
1080 node = xmlAddChild (object_node,
1081 xmlNewNode (ns, BAD_CAST qof_param->param_type));
1082 string_buffer =
1083 g_strdup (qof_book_merge_param_as_string
1084 (qof_param, ent));
1085 xmlNodeAddContent (node, BAD_CAST string_buffer);
1086 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
1087 qof_param->param_name);
1088 g_free (string_buffer);
1089 }
1090 }
1091 }
1092 param_list = g_slist_next (param_list);
1093 }
1094 }
1095
1096 static void
1097 qsf_foreach_obj_type (QofObject * qsf_obj, gpointer data)
1098 {
1099 QsfParam *params;
1100 QofBook *book;
1101 GSList *support;
1102
1103 g_return_if_fail (data != NULL);
1104 params = (QsfParam *) data;
1105 /* Skip unsupported objects */
1106 if ((qsf_obj->create == NULL) || (qsf_obj->foreach == NULL))
1107 {
1108 PINFO (" qsf_obj QOF support failed %s", qsf_obj->e_type);
1109 return;
1110 }
1111 params->qof_obj_type = qsf_obj->e_type;
1112 params->qsf_sequence = NULL;
1113 book = params->book;
1114 support = g_slist_copy (params->supported_types);
1115 g_slist_foreach (support, qsf_supported_parameters, params);
1116 qof_object_foreach (qsf_obj->e_type, book, qsf_entity_foreach, params);
1117 }
1118
1119 /*=====================================================
1120 Take a QofBook and prepare a QSF XML doc in memory
1121 =======================================================*/
1122 /* QSF only uses one QofBook per file - count may be removed later. */
1123 static xmlDocPtr
1124 qofbook_to_qsf (QofBook * book, QsfParam * params)
1125 {
1126 xmlNodePtr top_node, node;
1127 xmlDocPtr doc;
1128 gchar buffer[GUID_ENCODING_LENGTH + 1];
1129 const GUID *book_guid;
1130
1131 g_return_val_if_fail (book != NULL, NULL);
1132 params->book = book;
1133 params->referenceList =
1134 g_list_copy ((GList *) qof_book_get_data (book,
1135 ENTITYREFERENCE));
1136 doc = xmlNewDoc (BAD_CAST QSF_XML_VERSION);
1137 top_node = xmlNewNode (NULL, BAD_CAST QSF_ROOT_TAG);
1138 xmlDocSetRootElement (doc, top_node);
1139 xmlSetNs (top_node, xmlNewNs (top_node, BAD_CAST QSF_DEFAULT_NS,
1140 NULL));
1141 params->qsf_ns = top_node->ns;
1142 node =
1143 xmlNewChild (top_node, params->qsf_ns, BAD_CAST QSF_BOOK_TAG,
1144 NULL);
1145 params->book_node = node;
1146 xmlNewProp (node, BAD_CAST QSF_BOOK_COUNT, BAD_CAST "1");
1147 book_guid = qof_entity_get_guid ((QofEntity*)book);
1148 guid_to_string_buff (book_guid, buffer);
1149 xmlNewChild (params->book_node, params->qsf_ns,
1150 BAD_CAST QSF_BOOK_GUID, BAD_CAST buffer);
1151 params->output_doc = doc;
1152 params->book_node = node;
1153 qof_object_foreach_type (qsf_foreach_obj_type, params);
1154 return params->output_doc;
1155 }
1156
1157 static void
1158 write_qsf_from_book (const gchar *path, QofBook * book,
1159 QsfParam * params)
1160 {
1161 xmlDocPtr qsf_doc;
1162 gint write_result;
1163 QofBackend *be;
1164
1165 be = qof_book_get_backend (book);
1166 qsf_doc = qofbook_to_qsf (book, params);
1167 write_result = 0;
1168 PINFO (" use_gz_level=%" G_GINT64_FORMAT " encoding=%s",
1169 params->use_gz_level, params->encoding);
1170 if ((params->use_gz_level > 0) && (params->use_gz_level <= 9))
1171 xmlSetDocCompressMode (qsf_doc, params->use_gz_level);
1172 g_return_if_fail (qsf_is_valid
1173 (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
1174 write_result =
1175 xmlSaveFormatFileEnc (path, qsf_doc, params->encoding, 1);
1176 if (write_result < 0)
1177 {
1178 qof_error_set_be (be, qof_error_register
1179 (_("Could not write to '%s'. Check that you have "
1180 "permission to write to this file and that there is "
1181 "sufficient space to create it."), TRUE));
1182 return;
1183 }
1184 qof_object_mark_clean (book);
1185 }
1186
1187 static void
1188 write_qsf_to_stdout (QofBook * book, QsfParam * params)
1189 {
1190 xmlDocPtr qsf_doc;
1191
1192 qsf_doc = qofbook_to_qsf (book, params);
1193 g_return_if_fail (qsf_is_valid
1194 (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
1195 PINFO (" use_gz_level=%" G_GINT64_FORMAT " encoding=%s",
1196 params->use_gz_level, params->encoding);
1197 xmlSaveFormatFileEnc ("-", qsf_doc, params->encoding, 1);
1198 fprintf (stdout, "\n");
1199 qof_object_mark_clean (book);
1200 }
1201
1202 static void
1203 qsf_write_file (QofBackend * be, QofBook * book)
1204 {
1205 QSFBackend *qsf_be;
1206 QsfParam *params;
1207 gchar *path;
1208
1209 qsf_be = (QSFBackend *) be;
1210 params = qsf_be->params;
1211 /* if fullpath is blank, book_id was set to QOF_STDOUT */
1212 if (!qsf_be->fullpath || (*qsf_be->fullpath == '\0'))
1213 {
1214 write_qsf_to_stdout (book, params);
1215 return;
1216 }
1217 path = strdup (qsf_be->fullpath);
1218 write_qsf_from_book (path, book, params);
1219 g_free (path);
1220 }
1221
1222 KvpValue *
1223 string_to_kvp_value (const gchar * content, KvpValueType type)
1224 {
1225 gchar *tail;
1226 gint64 cm_i64;
1227 gdouble cm_double;
1228 QofNumeric cm_numeric;
1229 GUID *cm_guid;
1230 #ifndef QOF_DISABLE_DEPRECATED
1231 struct tm kvp_time;
1232 time_t kvp_time_t;
1233 Timespec cm_date;
1234 #endif
1235
1236 switch (type)
1237 {
1238 case KVP_TYPE_GINT64:
1239 {
1240 errno = 0;
1241 cm_i64 = strtoll (content, &tail, 0);
1242 if (errno == 0)
1243 {
1244 return kvp_value_new_gint64 (cm_i64);
1245 }
1246 break;
1247 }
1248 case KVP_TYPE_DOUBLE:
1249 {
1250 errno = 0;
1251 cm_double = strtod (content, &tail);
1252 if (errno == 0)
1253 return kvp_value_new_double (cm_double);
1254 break;
1255 }
1256 case KVP_TYPE_NUMERIC:
1257 {
1258 qof_numeric_from_string (content, &cm_numeric);
1259 return kvp_value_new_numeric (cm_numeric);
1260 break;
1261 }
1262 case KVP_TYPE_STRING:
1263 {
1264 return kvp_value_new_string (content);
1265 break;
1266 }
1267 case KVP_TYPE_GUID:
1268 {
1269 cm_guid = g_new0 (GUID, 1);
1270 if (TRUE == string_to_guid (content, cm_guid))
1271 return kvp_value_new_guid (cm_guid);
1272 break;
1273 }
1274 case KVP_TYPE_TIME :
1275 {
1276 QofDate *qd;
1277 QofTime *qt;
1278 KvpValue *retval;
1279
1280 qd = qof_date_parse (content, QOF_DATE_FORMAT_UTC);
1281 if(qd)
1282 {
1283 qt = qof_date_to_qtime (qd);
1284 retval = kvp_value_new_time (qt);
1285 qof_date_free (qd);
1286 qof_time_free (qt);
1287 return retval;
1288 }
1289 else
1290 PERR (" failed to parse date");
1291 }
1292 #ifndef QOF_DISABLE_DEPRECATED
1293 case KVP_TYPE_TIMESPEC:
1294 {
1295 strptime (content, QSF_XSD_TIME, &kvp_time);
1296 kvp_time_t = mktime (&kvp_time);
1297 timespecFromTime_t (&cm_date, kvp_time_t);
1298 return kvp_value_new_timespec (cm_date);
1299 break;
1300 }
1301 #endif
1302 case KVP_TYPE_BOOLEAN :
1303 {
1304 gboolean val;
1305 val = qof_util_bool_to_int (content);
1306 return kvp_value_new_boolean (val);
1307 }
1308 case KVP_TYPE_BINARY:
1309 // return kvp_value_new_binary(value->value.binary.data,
1310 // value->value.binary.datasize);
1311 break;
1312 case KVP_TYPE_GLIST:
1313 // return kvp_value_new_glist(value->value.list);
1314 break;
1315 case KVP_TYPE_FRAME:
1316 // return kvp_value_new_frame(value->value.frame);
1317 break;
1318 }
1319 return NULL;
1320 }
1321
1322 /* ======================================================
1323 Commit XML data from file to QofEntity in a QofBook
1324 ========================================================= */
1325 void
1326 qsf_object_commitCB (gpointer key, gpointer value, gpointer data)
1327 {
1328 QsfParam *params;
1329 QsfObject *object_set;
1330 xmlNodePtr node;
1331 QofEntityReference *reference;
1332 QofEntity *qsf_ent;
1333 QofBook *targetBook;
1334 const gchar *qof_type, *parameter_name;
1335 QofIdType obj_type, reference_type;
1336 gchar *tail;
1337 /* cm_ prefix used for variables that hold the data to commit */
1338 QofNumeric cm_numeric;
1339 gdouble cm_double;
1340 gboolean cm_boolean;
1341 gint32 cm_i32;
1342 gint64 cm_i64;
1343 gchar cm_char, (*char_getter) (xmlNodePtr);
1344 GUID *cm_guid;
1345 KvpFrame *cm_kvp;
1346 KvpValue *cm_value;
1347 KvpValueType cm_type;
1348 QofSetterFunc cm_setter;
1349 const QofParam *cm_param;
1350 void (*string_setter) (QofEntity *, const gchar *);
1351 void (*time_setter) (QofEntity *, QofTime *);
1352 void (*numeric_setter) (QofEntity *, QofNumeric);
1353 void (*double_setter) (QofEntity *, gdouble);
1354 void (*boolean_setter) (QofEntity *, gboolean);
1355 void (*i32_setter) (QofEntity *, gint32);
1356 void (*i64_setter) (QofEntity *, gint64);
1357 void (*char_setter) (QofEntity *, gchar);
1358
1359 g_return_if_fail (data && value && key);
1360 params = (QsfParam *) data;
1361 node = (xmlNodePtr) value;
1362 parameter_name = (const gchar *) key;
1363 qof_type = (gchar *) node->name;
1364 qsf_ent = params->qsf_ent;
1365 targetBook = params->book;
1366 obj_type =
1367 (gchar *) xmlGetProp (node->parent, BAD_CAST QSF_OBJECT_TYPE);
1368 if (0 == safe_strcasecmp (obj_type, parameter_name))
1369 {
1370 return;
1371 }
1372 cm_setter = qof_class_get_parameter_setter (obj_type, parameter_name);
1373 cm_param = qof_class_get_parameter (obj_type, parameter_name);
1374 object_set = params->object_set;
1375 if (safe_strcmp (qof_type, QOF_TYPE_STRING) == 0)
1376 {
1377 string_setter = (void (*)(QofEntity *, const gchar *)) cm_setter;
1378 if (string_setter != NULL)
1379 {
1380 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1381 string_setter (qsf_ent, (gchar *) xmlNodeGetContent (node));
1382 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1383 }
1384 }
1385 #ifndef QOF_DISABLE_DEPRECATED
1386 /* use convert here to read "date" */
1387 if ((params->convert != 0) &&
1388 ((safe_strcmp (qof_type, QOF_TYPE_DATE) == 0) ||
1389 (safe_strcmp (qof_type, QOF_TYPE_TIME) == 0)))
1390 {
1391 /* just reading the same value from a different tag */
1392 #else
1393 if (safe_strcmp (qof_type, QOF_TYPE_TIME) == 0)
1394 {
1395 #endif
1396 time_setter = (void (*)(QofEntity *, QofTime*)) cm_setter;
1397 if (time_setter != NULL)
1398 {
1399 QofDate *qd;
1400 QofTime *qt;
1401
1402 qd = qof_date_parse (
1403 (const gchar*) xmlNodeGetContent (node),
1404 QOF_DATE_FORMAT_UTC);
1405 if(qd)
1406 {
1407 qt = qof_date_to_qtime (qd);
1408 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1409 time_setter (qsf_ent, qt);
1410 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1411 qof_date_free (qd);
1412 }
1413 else
1414 PERR (" failed to parse date string");
1415 }
1416 }
1417 #ifndef QOF_DISABLE_DEPRECATED
1418 if ((params->convert == 0) &&
1419 (safe_strcmp (qof_type, QOF_TYPE_DATE) == 0))
1420 {
1421 void (*date_setter) (QofEntity *, Timespec);
1422 struct tm qsf_time;
1423 time_t qsf_time_t;
1424 Timespec cm_date;
1425 const gchar *timechk;
1426
1427 memset (&qsf_time, '\0', sizeof (qsf_time));
1428 cm_date.tv_nsec = 0;
1429 cm_date.tv_sec = 0;
1430 date_setter = (void (*)(QofEntity *, Timespec)) cm_setter;
1431 timechk = NULL;
1432 timechk =
1433 strptime ((char *) xmlNodeGetContent (node), QSF_XSD_TIME,
1434 &qsf_time);
1435 g_return_if_fail (timechk != NULL);
1436 qsf_time_t = mktime (&qsf_time);
1437 if (qsf_time_t != -3600)
1438 {
1439 timespecFromTime_t (&cm_date, qsf_time_t);
1440 if (date_setter != NULL)
1441 {
1442 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1443 date_setter (qsf_ent, cm_date);
1444 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1445 }
1446 }
1447 }
1448 #endif
1449 if ((safe_strcmp (qof_type, QOF_TYPE_NUMERIC) == 0) ||
1450 (safe_strcmp (qof_type, QOF_TYPE_DEBCRED) == 0))
1451 {
1452 gchar *tmp;
1453 numeric_setter = (void (*)(QofEntity *, QofNumeric)) cm_setter;
1454 tmp = (char *) xmlNodeGetContent (node);
1455 qof_numeric_from_string (tmp, &cm_numeric);
1456 g_free (tmp);
1457 if (numeric_setter != NULL)
1458 {
1459 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1460 numeric_setter (qsf_ent, cm_numeric);
1461 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1462 }
1463 }
1464 if (safe_strcmp (qof_type, QOF_TYPE_GUID) == 0)
1465 {
1466 cm_guid = g_new0 (GUID, 1);
1467 if (TRUE !=
1468 string_to_guid ((gchar *) xmlNodeGetContent (node), cm_guid))
1469 {
1470 qof_error_set_be (params->be, qof_error_register(
1471 _("The selected QSF object file '%s' contains one or "
1472 "more invalid GUIDs. The file cannot be processed - "
1473 "please check the source of the file and try again."),
1474 TRUE));
1475 PINFO (" string to guid conversion failed for %s:%s:%s",
1476 xmlNodeGetContent (node), obj_type, qof_type);
1477 return;
1478 }
1479 reference_type =
1480 (gchar *) xmlGetProp (node, BAD_CAST QSF_OBJECT_TYPE);
1481 if (0 == safe_strcmp (QOF_PARAM_GUID, reference_type))
1482 {
1483 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1484 qof_entity_set_guid (qsf_ent, cm_guid);
1485 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1486 }
1487 else
1488 {
1489 reference = qof_entity_get_reference_from (qsf_ent, cm_param);
1490 if (reference)
1491 {
1492 params->referenceList =
1493 g_list_append (params->referenceList, reference);
1494 }
1495 }
1496 }
1497 if (safe_strcmp (qof_type, QOF_TYPE_INT32) == 0)
1498 {
1499 errno = 0;
1500 cm_i32 =
1501 (gint32) strtol ((char *) xmlNodeGetContent (node), &tail, 0);
1502 if (errno == 0)
1503 {
1504 i32_setter = (void (*)(QofEntity *, gint32)) cm_setter;
1505 if (i32_setter != NULL)
1506 {
1507 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1508 i32_setter (qsf_ent, cm_i32);
1509 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1510 }
1511 }
1512 else
1513 qof_error_set_be (params->be, params->err_overflow);
1514 }
1515 if (safe_strcmp (qof_type, QOF_TYPE_INT64) == 0)
1516 {
1517 errno = 0;
1518 cm_i64 = strtoll ((gchar *) xmlNodeGetContent (node), &tail, 0);
1519 if (errno == 0)
1520 {
1521 i64_setter = (void (*)(QofEntity *, gint64)) cm_setter;
1522 if (i64_setter != NULL)
1523 {
1524 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1525 i64_setter (qsf_ent, cm_i64);
1526 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1527 }
1528 }
1529 else
1530 qof_error_set_be (params->be, params->err_overflow);
1531 }
1532 if (safe_strcmp (qof_type, QOF_TYPE_DOUBLE) == 0)
1533 {
1534 errno = 0;
1535 cm_double = strtod ((gchar *) xmlNodeGetContent (node), &tail);
1536 if (errno == 0)
1537 {
1538 double_setter = (void (*)(QofEntity *, gdouble)) cm_setter;
1539 if (double_setter != NULL)
1540 {
1541 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1542 double_setter (qsf_ent, cm_double);
1543 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1544 }
1545 }
1546 }
1547 if (safe_strcmp (qof_type, QOF_TYPE_BOOLEAN) == 0)
1548 {
1549 if (0 == safe_strcasecmp ((gchar *) xmlNodeGetContent (node),
1550 QSF_XML_BOOLEAN_TEST))
1551 cm_boolean = TRUE;
1552 else
1553 cm_boolean = FALSE;
1554 boolean_setter = (void (*)(QofEntity *, gboolean)) cm_setter;
1555 if (boolean_setter != NULL)
1556 {
1557 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1558 boolean_setter (qsf_ent, cm_boolean);
1559 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1560 }
1561 }
1562 if (safe_strcmp (qof_type, QOF_TYPE_KVP) == 0)
1563 {
1564 cm_type =
1565 qsf_to_kvp_helper ((gchar *)
1566 xmlGetProp (node, BAD_CAST QSF_OBJECT_VALUE));
1567 if (!cm_type)
1568 return;
1569 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1570 cm_value =
1571 string_to_kvp_value ((gchar *) xmlNodeGetContent (node),
1572 cm_type);
1573 cm_kvp = (KvpFrame *) cm_param->param_getfcn (qsf_ent, cm_param);
1574 cm_kvp = kvp_frame_set_value (cm_kvp, (gchar *) xmlGetProp (node,
1575 BAD_CAST QSF_OBJECT_KVP), cm_value);
1576 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1577 g_free (cm_value);
1578 }
1579 if (safe_strcmp (qof_type, QOF_TYPE_COLLECT) == 0)
1580 {
1581 QofCollection *qsf_coll;
1582 QofIdType type;
1583 QofEntityReference *reference;
1584 QofParam *copy_param;
1585 /* retrieve the *type* of the collection, ignore any contents. */
1586 qsf_coll = cm_param->param_getfcn (qsf_ent, cm_param);
1587 type = qof_collection_get_type (qsf_coll);
1588 cm_guid = g_new0 (GUID, 1);
1589 if (TRUE !=
1590 string_to_guid ((gchar *) xmlNodeGetContent (node), cm_guid))
1591 {
1592 qof_error_set_be (params->be, (qof_error_register(
1593 _("The selected QSF object file '%s' contains one or "
1594 "more invalid 'collect' values. The file cannot be processed - "
1595 "please check the source of the file and try again."),
1596 TRUE)));
1597 PINFO (" string to guid collect failed for %s",
1598 xmlNodeGetContent (node));
1599 return;
1600 }
1601 /* create a QofEntityReference with this type and GUID.
1602 there is only one entity each time.
1603 cm_guid contains the GUID of the reference.
1604 type is the type of the reference. */
1605 reference = g_new0 (QofEntityReference, 1);
1606 reference->type = g_strdup (qsf_ent->e_type);
1607 reference->ref_guid = cm_guid;
1608 reference->ent_guid = &qsf_ent->guid;
1609 copy_param = g_new0 (QofParam, 1);
1610 copy_param->param_name = g_strdup (cm_param->param_name);
1611 copy_param->param_type = g_strdup (cm_param->param_type);
1612 reference->param = copy_param;
1613 params->referenceList =
1614 g_list_append (params->referenceList, reference);
1615 }
1616 if (safe_strcmp (qof_type, QOF_TYPE_CHAR) == 0)
1617 {
1618 char_getter = (gchar (*)(xmlNodePtr)) xmlNodeGetContent;
1619 cm_char = char_getter (node);
1620 char_setter = (void (*)(QofEntity *, gchar)) cm_setter;
1621 if (char_setter != NULL)
1622 {
1623 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
1624 char_setter (qsf_ent, cm_char);
1625 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
1626 }
1627 }
1628 }
1629
1630 static QofBackend *
1631 qsf_backend_new (void)
1632 {
1633 QSFBackend *qsf_be;
1634 QofBackend *be;
1635
1636 qsf_be = g_new0 (QSFBackend, 1);
1637 be = (QofBackend *) qsf_be;
1638 qof_backend_init (be);
1639 qsf_be->params = g_new0 (QsfParam, 1);
1640 qsf_be->params->be = be;
1641 qsf_param_init (qsf_be->params);
1642 qsf_be->be.session_begin = qsf_session_begin;
1643
1644 be->session_end = qsf_session_end;
1645 be->destroy_backend = qsf_destroy_backend;
1646 be->load = qsf_file_type;
1647 be->save_may_clobber_data = NULL;
1648 /* The QSF backend will always load and save the entire QSF XML file. */
1649 be->begin = NULL;
1650 be->commit = NULL;
1651 be->rollback = NULL;
1652 /* QSF uses the built-in SQL, not a dedicated SQL server. */
1653 be->compile_query = NULL;
1654 be->free_query = NULL;
1655 be->run_query = NULL;
1656 be->counter = NULL;
1657 /* The QSF backend is not multi-user. */
1658 be->events_pending = NULL;
1659 be->process_events = NULL;
1660
1661 be->sync = qsf_write_file;
1662 /* use for maps, later. */
1663 be->load_config = qsf_load_config;
1664 be->get_config = qsf_get_config;
1665
1666 qsf_be->fullpath = NULL;
1667 return be;
1668 }
1669
1670 /* The QOF method of loading each backend.
1671 QSF is loaded as a GModule using the QOF method - QofBackendProvider.
1672 */
1673 static void
1674 qsf_provider_free (QofBackendProvider * prov)
1675 {
1676 prov->provider_name = NULL;
1677 prov->access_method = NULL;
1678 g_free (prov);
1679 }
1680
1681 void
1682 qsf_provider_init (void)
1683 {
1684 QofBackendProvider *prov;
1685
1686 bindtextdomain (PACKAGE, LOCALE_DIR);
1687 prov = g_new0 (QofBackendProvider, 1);
1688 prov->provider_name = "QSF Backend Version 0.4";
1689 prov->access_method = "file";
1690 prov->partial_book_supported = TRUE;
1691 prov->backend_new = qsf_backend_new;
1692 prov->check_data_type = qsf_determine_file_type;
1693 prov->provider_free = qsf_provider_free;
1694 qof_backend_register_provider (prov);
1695 }
KVP_TYPE_TIMESPEC
Definition: kvpframe.h:121
QsfMetadata_s
QSF Parameters.
Definition: qsf-xml.h:469
QOF_TYPE_DATE
#define QOF_TYPE_DATE
Definition: deprecated.h:336
QsfMetadata_s::qsf_ns
xmlNsPtr qsf_ns
Definition: qsf-xml.h:507
QOF_DATE_FORMAT_UTC
#define QOF_DATE_FORMAT_UTC
QOF UTC format, xsd:date compatible. QOF_UTC_DATE_FORMAT "%Y-%m-%dT%H:%M:%SZ".
Definition: qofdate.h:277
qof_error_register
QofErrorId qof_error_register(const gchar *err_message, gboolean use_file)
Generate and register a new error.
Definition: qoferror.c:91
QofBackend_s::fullpath
gchar * fullpath
Definition: qofbackend-p.h:338
QofBackend_s::save_may_clobber_data
gboolean(* save_may_clobber_data)(QofBackend *)
Definition: qofbackend-p.h:320
PERR
#define PERR(format, args...)
Definition: qoflog.h:183
qof_object_new_instance
gpointer qof_object_new_instance(QofIdTypeConst type_name, QofBook *book)
Definition: qofobject.c:42
qof_entity_reference::ent_guid
const GUID * ent_guid
Definition: qofreference.h:115
QsfMetadata_s::full_kvp_path
gchar * full_kvp_path
Definition: qsf-xml.h:537
qof_time_stamp_now
gchar * qof_time_stamp_now(void)
Definition: qoftime.c:469
QOF_DATE_FORMAT_ISO
#define QOF_DATE_FORMAT_ISO
Short ISO form. "%F".
Definition: qofdate.h:268
QOF_TYPE_COLLECT
#define QOF_TYPE_COLLECT
Definition: qofclass.h:93
QSF_DATE_CONVERT
#define QSF_DATE_CONVERT
Convert QOF_TYPE_DATE to QOF_TYPE_TIME.
Definition: qof-backend-qsf.h:228
qof_entity_reference::type
QofIdType type
Definition: qofreference.h:109
QofIdType
const gchar * QofIdType
Definition: qofid.h:81
PINFO
#define PINFO(format, args...)
Definition: qoflog.h:199
QofInstance_s
Definition: qofinstance-p.h:35
qof_book_get_collection
QofCollection * qof_book_get_collection(QofBook *book, QofIdType entity_type)
Definition: qofbook.c:220
qof_class_is_registered
gboolean qof_class_is_registered(QofIdTypeConst obj_name)
Definition: qofclass.c:132
Timespec
struct timespec64 Timespec
QSF_OBJECT_COUNT
#define QSF_OBJECT_COUNT
Definition: qsf-xml.h:105
QofNumeric
struct _QofNumeric QofNumeric
A rational-number type.
Definition: qofnumeric.h:61
qof_date_free
void qof_date_free(QofDate *date)
Definition: qofdate.c:608
QSF_OBJECT_KVP
#define QSF_OBJECT_KVP
Definition: qsf-xml.h:127
qof_class_param_foreach
void qof_class_param_foreach(QofIdTypeConst obj_name, QofParamForeachCB cb, gpointer user_data)
Definition: qofclass.c:267
qof_backend_register_provider
void qof_backend_register_provider(QofBackendProvider *)
Definition: qofsession.c:59
QSF_ROOT_TAG
#define QSF_ROOT_TAG
Definition: qsf-xml.h:81
_QofParam
Definition: qofclass.h:195
is_qsf_object
gboolean is_qsf_object(const gchar *path)
Validate a QSF file and identify a suitable QSF map.
Definition: qsf-xml.c:219
qof_class_get_parameter_setter
QofSetterFunc qof_class_get_parameter_setter(QofIdTypeConst obj_name, const gchar *parameter)
Definition: qofclass.c:182
_QofSession
Definition: qofsession-p.h:35
QofBackendProvider_s
Definition: qofbackend-p.h:238
qof_date_get_current
QofDate * qof_date_get_current(void)
Definition: qofdate.c:582
KvpValueType
KvpValueType
possible types in the union KvpValue
Definition: kvpframe.h:87
QofEntity_s
Definition: qofid.h:147
qof_object_foreach
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofEntityForeachCB cb, gpointer user_data)
Definition: qofobject.c:174
string_to_guid
gboolean string_to_guid(const gchar *string, GUID *guid)
KVP_TYPE_GUID
Unique identifier.
Definition: kvpframe.h:118
QsfMetadata_s::count
gint count
Definition: qsf-xml.h:476
QofBackendOption_s::description
const gchar * description
Definition: qofbackend.h:119
QsfMetadata_s::file_type
QsfType file_type
Definition: qsf-xml.h:472
QsfMetadata_s::knowntype
gboolean knowntype
Definition: qsf-xml.h:521
qof_book_get_data
gpointer qof_book_get_data(QofBook *book, const gchar *key)
Definition: qofbook.c:212
qsf_is_valid
gboolean qsf_is_valid(const gchar *schema_dir, const gchar *schema_filename, xmlDocPtr doc)
Compares an xmlDoc in memory against the schema file.
Definition: qsf-xml.c:75
QofBackendProvider_s::partial_book_supported
gboolean partial_book_supported
Partial QofBook handler.
Definition: qofbackend-p.h:254
QofErrorId
gint32 QofErrorId
The ID of this error.
Definition: qofbackend.h:54
QsfMetadata_s::qsf_ent
QofEntity * qsf_ent
Definition: qsf-xml.h:517
KvpFrame
struct _KvpFrame KvpFrame
Definition: kvpframe.h:74
safe_strcasecmp
gint safe_strcasecmp(const gchar *da, const gchar *db)
Definition: qofutil.c:92
qof_date_print
gchar * qof_date_print(const QofDate *date, QofDateFormat df)
Convert a QofDate to a timestamp according to the specified date format.
Definition: qofdate.c:547
is_qsf_object_be
gboolean is_qsf_object_be(QsfParam *params)
Validate a QSF file and identify a suitable QSF map.
Definition: qsf-xml.c:299
timespec64
Definition: qoftime.h:97
QsfMetadata_s::be
QofBackend * be
Definition: qsf-xml.h:519
QSF_OBJECT_TAG
#define QSF_OBJECT_TAG
Definition: qsf-xml.h:101
kvp_value_new_boolean
KvpValue * kvp_value_new_boolean(gboolean value)
Definition: kvpframe.c:1226
KVP_TYPE_GLIST
Definition: kvpframe.h:132
OUR_QSF_OBJ
Definition: qsf-xml.h:52
kvp_value_to_qof_type_helper
static QofIdTypeConst kvp_value_to_qof_type_helper(KvpValueType n)
Map a KvpValue to a QofIdType.
Definition: qof-sqlite.c:145
qof_book_merge_param_as_string
gchar * qof_book_merge_param_as_string(QofParam *qtparam, QofEntity *qtEnt)
provides easy string access to parameter data for dialogue use
Definition: qofbookmerge.c:1010
qof_entity_reference::ref_guid
GUID * ref_guid
Definition: qofreference.h:112
qof_error_check_be
QofErrorId qof_error_check_be(QofBackend *be)
Check for errors.
Definition: qoferror.c:234
QsfMetadata_s::qsf_sequence
GSList * qsf_sequence
Definition: qsf-xml.h:480
KVP_TYPE_FRAME
Definition: kvpframe.h:134
qof_backend_complete_frame
KvpFrame * qof_backend_complete_frame(QofBackend *be)
Definition: qofbackend.c:200
_QofObject::create
gpointer(* create)(QofBook *)
Definition: qofobject.h:80
qsf-xml.h
Private QSF header - not for use by applications.
qof_util_bool_to_int
gint qof_util_bool_to_int(const gchar *val)
Definition: qofutil.c:249
kvp_frame_is_empty
gboolean kvp_frame_is_empty(KvpFrame *frame)
Definition: kvpframe.c:137
QSF_BOOK_COUNT
#define QSF_BOOK_COUNT
Definition: qsf-xml.h:99
LEAVE
#define LEAVE(format, args...)
Definition: qoflog.h:227
GUID_ENCODING_LENGTH
#define GUID_ENCODING_LENGTH
Definition: guid.h:64
QSF_OBJECT_TYPE
#define QSF_OBJECT_TYPE
Definition: qsf-xml.h:103
qof_date_to_qtime
QofTime * qof_date_to_qtime(const QofDate *qd)
Definition: qofdate.c:892
QofDate_s
Full range replacement for struct tm.
Definition: qofdate.h:138
kvp_frame_set_value
KvpFrame * kvp_frame_set_value(KvpFrame *frame, const gchar *key_path, const KvpValue *value)
Copy the KvpValue into the frame.
Definition: kvpframe.c:499
QofSetterFunc
void(* QofSetterFunc)(gpointer, gpointer)
Definition: qofclass.h:176
qof_time_get_current
QofTime * qof_time_get_current(void)
Get the current QofTime.
Definition: qoftime.c:362
KVP_TYPE_NUMERIC
128bit denominator/numerator maths.
Definition: kvpframe.h:106
qofobject-p.h
the Core Object Registration/Lookup Private Interface
QofCollection
struct QofCollection_s QofCollection
Definition: qofid.h:138
qof_class_get_parameter
const QofParam * qof_class_get_parameter(QofIdTypeConst obj_name, const gchar *parameter)
Definition: qofclass.c:146
qof_util_param_edit
gboolean qof_util_param_edit(QofInstance *inst, const QofParam *param)
Prepare to edit a parameter.
Definition: qofutil.c:278
QsfMetadata_s::encoding
const gchar * encoding
Definition: qsf-xml.h:547
qof_date_parse
QofDate * qof_date_parse(const gchar *str, QofDateFormat df)
Convert a timestamp to a QofTime.
Definition: qofdate.c:525
KvpValue
struct _KvpValue KvpValue
Definition: kvpframe.h:78
qof_entity_reference::choice_type
QofIdType choice_type
Definition: qofreference.h:107
is_our_qsf_object
gboolean is_our_qsf_object(const gchar *path)
Validate a QSF file.
Definition: qsf-xml.c:180
QsfMetadata_s::input_doc
xmlDocPtr input_doc
Definition: qsf-xml.h:489
IS_QSF_MAP
Definition: qsf-xml.h:46
kvp_value_new_timespec
KvpValue * kvp_value_new_timespec(Timespec timespec)
Definition: deprecated.c:1482
QsfNodeIterate
One iterator, two typedefs.
Definition: qsf-xml.h:689
qof_collection_count
guint qof_collection_count(QofCollection *col)
Definition: qofid.c:351
QsfMetadata_s::map_path
gchar * map_path
Definition: qsf-xml.h:535
QSF_BOOK_TAG
#define QSF_BOOK_TAG
Definition: qsf-xml.h:94
qof_backend_init
void qof_backend_init(QofBackend *be)
Definition: qofbackend.c:37
QSF_XML_BOOLEAN_TEST
#define QSF_XML_BOOLEAN_TEST
Definition: qsf-xml.h:417
timespecFromTime_t
void timespecFromTime_t(Timespec *ts, time_t t)
Definition: deprecated.c:304
qof_numeric_from_string
gboolean qof_numeric_from_string(const gchar *str, QofNumeric *n)
Definition: qofnumeric.c:1121
qof_collection_lookup_entity
QofEntity * qof_collection_lookup_entity(QofCollection *col, const GUID *guid)
Definition: qofid.c:321
qsf_map_prepare_list
GList ** qsf_map_prepare_list(GList **maps)
Prepare the default list of maps.
Definition: qsf-backend.c:167
qof_entity_get_reference_from
QofEntityReference * qof_entity_get_reference_from(QofEntity *ent, const QofParam *param)
Get a reference from this entity to another entity.
Definition: qofreference.c:167
QsfMetadata_s::qsf_object_list
GList * qsf_object_list
Definition: qsf-xml.h:478
qof_time_free
void qof_time_free(QofTime *qt)
Free a QofTime when no longer required.
Definition: qoftime.c:56
qof_backend_prepare_option
void qof_backend_prepare_option(QofBackend *be, QofBackendOption *option)
Definition: qofbackend.c:111
qof_collection_foreach
void qof_collection_foreach(QofCollection *col, QofEntityForeachCB cb_func, gpointer user_data)
Definition: qofid.c:421
IS_QSF_OBJ
Definition: qsf-xml.h:48
QOF_SUCCESS
#define QOF_SUCCESS
Definition: qoferror.h:124
QsfMetadata_s::supported_types
GSList * supported_types
Definition: qsf-xml.h:487
KVP_TYPE_GINT64
64bit integer
Definition: kvpframe.h:94
qsf_node_foreach
void qsf_node_foreach(xmlNodePtr parent, QsfNodeCB cb, struct QsfNodeIterate *qsfiter, QsfParam *params)
Definition: qsf-xml.c:116
qof_backend_option_foreach
void qof_backend_option_foreach(KvpFrame *config, QofBackendOptionCB cb, gpointer data)
Definition: qofbackend.c:383
_QofObject
Definition: qofobject.h:70
QofBackendProvider_s::provider_free
void(* provider_free)(QofBackendProvider *)
Definition: qofbackend-p.h:280
_QofNumeric
Definition: qofnumeric.h:52
QsfMetadata_s::lister
xmlNodePtr lister
Definition: qsf-xml.h:505
DEBUG
#define DEBUG(format, args...)
Definition: qoflog.h:208
QofBackendProvider_s::backend_new
QofBackend *(* backend_new)(void)
Definition: qofbackend-p.h:260
string_to_kvp_value
KvpValue * string_to_kvp_value(const gchar *content, KvpValueType type)
Convert a string value into KvpValue.
Definition: qsf-backend.c:1223
QsfMetadata_s::convert
gint64 convert
Definition: qsf-xml.h:549
QofBackendOption_s::option_name
const gchar * option_name
Definition: qofbackend.h:118
qof-backend-qsf.h
QSF API - Backend, maps, objects and configuration.
QsfMetadata_s::referenceList
GList * referenceList
Definition: qsf-xml.h:482
QsfMetadata_s::use_gz_level
gint64 use_gz_level
Definition: qsf-xml.h:539
guid_to_string_buff
gchar * guid_to_string_buff(const GUID *guid, gchar *buff)
kvp_value_to_bare_string
gchar * kvp_value_to_bare_string(const KvpValue *val)
General purpose function to convert any KvpValue to a string.
Definition: kvpframe.c:1848
qof_util_param_commit
gboolean qof_util_param_commit(QofInstance *inst, const QofParam *param)
Commit this parameter change, with undo support.
Definition: qofutil.c:306
QsfMetadata_s::book_node
xmlNodePtr book_node
Definition: qsf-xml.h:503
qof_book_set_data
void qof_book_set_data(QofBook *book, const gchar *key, gpointer data)
Definition: qofbook.c:191
QsfMetadata_s::qof_param
QofParam * qof_param
Definition: qsf-xml.h:523
QsfMetadata_s::qsf_parameter_hash
GHashTable * qsf_parameter_hash
Definition: qsf-xml.h:484
QofInstance_s::entity
QofEntity entity
Definition: qofinstance-p.h:38
qof_entity_reference::param
const QofParam * param
Definition: qofreference.h:113
qof_class_get_referenceList
GList * qof_class_get_referenceList(QofIdTypeConst type)
List of the parameters that could be references.
Definition: qofclass.c:332
QofBackendProvider_s::access_method
const gchar * access_method
Definition: qofbackend-p.h:247
QsfMetadata_s::book
QofBook * book
Definition: qsf-xml.h:529
QSF_ENCODING
#define QSF_ENCODING
Encoding string.
Definition: qof-backend-qsf.h:199
kvp_frame_for_each_slot
void kvp_frame_for_each_slot(KvpFrame *f, KvpValueForeachCB proc, gpointer data)
Definition: kvpframe.c:1650
ENTITYREFERENCE
#define ENTITYREFERENCE
Definition: qofreference.h:137
qof_collection_get_type
QofIdType qof_collection_get_type(QofCollection *col)
Definition: qofid.c:175
_GUID
Definition: guid.h:53
is_qsf_map_be
gboolean is_qsf_map_be(QsfParam *params)
Validate a QSF map file.
Definition: qsf-xml-map.c:320
QofBackendProvider_s::check_data_type
gboolean(* check_data_type)(const gchar *)
Distinguish two providers with same access method.
Definition: qofbackend-p.h:277
is_qsf_map
gboolean is_qsf_map(const gchar *path)
Validate a QSF map file.
Definition: qsf-xml-map.c:372
QsfMetadata_s::map_files
GList * map_files
Definition: qsf-xml.h:545
QOF_STDOUT
#define QOF_STDOUT
Allow session data to be printed to stdout.
Definition: qofsession.h:385
QsfMetadata_s::qof_obj_type
QofIdType qof_obj_type
Definition: qsf-xml.h:511
QSF_XSD_TIME
#define QSF_XSD_TIME
Definition: qsf-xml.h:414
QofIdTypeConst
const gchar * QofIdTypeConst
Definition: qofid.h:83
QSF_OBJECT_VALUE
#define QSF_OBJECT_VALUE
Definition: qsf-xml.h:129
QofTime
struct QofTime64 QofTime
Use a 64-bit signed int QofTime.
Definition: qoftime.h:120
is_our_qsf_object_be
gboolean is_our_qsf_object_be(QsfParam *params)
Validate a QSF file and determine type.
Definition: qsf-xml.c:243
KVP_TYPE_BOOLEAN
Simple boolean type.
Definition: kvpframe.h:140
qof_entity_get_guid
const GUID * qof_entity_get_guid(QofEntity *ent)
Definition: qofid.c:105
QofBackendOption_s::tooltip
const gchar * tooltip
Definition: qofbackend.h:120
KVP_TYPE_BINARY
Definition: kvpframe.h:130
qof_entity_reference
External references in a partial QofBook.
Definition: qofreference.h:105
qof_book_get_backend
QofBackend * qof_book_get_backend(QofBook *book)
Retrieve the backend used by this book.
Definition: qofbook.c:154
QSF_OBJECT_SCHEMA
#define QSF_OBJECT_SCHEMA
Definition: qsf-xml.h:420
QsfMetadata_s::output_node
xmlNodePtr output_node
Definition: qsf-xml.h:499
qof_object_is_choice
gboolean qof_object_is_choice(QofIdType type)
Does this object contain a choice parameter?
Definition: qofchoice.c:45
KVP_TYPE_STRING
standard C string
Definition: kvpframe.h:112
QsfMetadata_s::filepath
gchar * filepath
Definition: qsf-xml.h:533
QsfObject_s
Holds a description of the QofObject.
Definition: qsf-xml.h:63
qof_entity_set_guid
void qof_entity_set_guid(QofEntity *ent, const GUID *guid)
Definition: qofid.c:92
_QofBook
Definition: qofbook-p.h:48
QsfMetadata_s::qof_type
const gchar * qof_type
Definition: qsf-xml.h:509
_QofObject::foreach
void(* foreach)(QofCollection *, QofEntityForeachCB, gpointer)
Definition: qofobject.h:105
safe_strcmp
gint safe_strcmp(const gchar *da, const gchar *db)
Definition: qofutil.c:72
kvp_value_get_frame
KvpFrame * kvp_value_get_frame(const KvpValue *value)
Definition: kvpframe.c:1549
KVP_TYPE_DOUBLE
standard C double type
Definition: kvpframe.h:100
QSF_MAP_FILES
#define QSF_MAP_FILES
selected QSF maps
Definition: qof-backend-qsf.h:194
qsf_object_convert
xmlDocPtr qsf_object_convert(xmlDocPtr mapDoc, xmlNodePtr qsf_root, QsfParam *params)
Convert between QSF objects.
Definition: qsf-xml-map.c:954
QofBackendProvider_s::provider_name
const gchar * provider_name
Definition: qofbackend-p.h:241
qsf_book_node_handler
void qsf_book_node_handler(xmlNodePtr child, xmlNsPtr qsf_ns, QsfParam *params)
Book and book-guid node handler.
Definition: qsf-xml.c:424
QSF_DEFAULT_NS
#define QSF_DEFAULT_NS
Definition: qsf-xml.h:87
QsfMetadata_s::object_set
QsfObject * object_set
Definition: qsf-xml.h:474
QOF_TYPE_CHOICE
#define QOF_TYPE_CHOICE
Identify an object as containing a choice.
Definition: qofchoice.h:103
ENTER
#define ENTER(format, args...)
Definition: qoflog.h:217
QsfMetadata_s::output_doc
xmlDocPtr output_doc
Definition: qsf-xml.h:491
qof_object_foreach_type
void qof_object_foreach_type(QofForeachTypeCB cb, gpointer user_data)
Definition: qofobject.c:140
QofBackendOption_s::type
KvpValueType type
Definition: qofbackend.h:116
QofBackend_s
Definition: qofbackend-p.h:283
QofLogModule
const gchar * QofLogModule
Definition: qofid.h:85
QSF_XML_VERSION
#define QSF_XML_VERSION
Definition: qsf-xml.h:107
KVP_TYPE_TIME
64bit time/date handling.
Definition: kvpframe.h:128
QSF_BOOK_GUID
#define QSF_BOOK_GUID
Definition: qsf-xml.h:97
QofBackendOption_s
Definition: qofbackend.h:114
QSF_UNDEF
Definition: qsf-xml.h:44
QofBackendOption_s::value
gpointer value
Definition: qofbackend.h:121
QSF_COMPRESS
#define QSF_COMPRESS
compression level
Definition: qof-backend-qsf.h:177
qof_backend_prepare_frame
void qof_backend_prepare_frame(QofBackend *be)
Definition: qofbackend.c:99
qsf_provider_init
void qsf_provider_init(void)
Describe this backend to the application.
Definition: qsf-backend.c:1682