28 #include <libxml/xmlmemory.h>
29 #include <libxml/tree.h>
30 #include <libxml/parser.h>
31 #include <libxml/xmlschemas.h>
38 #define QSF_TYPE_BINARY "binary"
39 #define QSF_TYPE_GLIST "glist"
40 #define QSF_TYPE_FRAME "frame"
44 static void qsf_object_commitCB (gpointer key, gpointer value,
54 typedef struct QSFBackend_s QSFBackend;
62 g_return_if_fail (params);
81 PINFO (
" converting date into time on file write.");
92 qsf_be = (QSFBackend *) be;
93 g_return_if_fail (qsf_be->params);
94 params = qsf_be->params;
111 qsf_be = (QSFBackend *) be;
112 g_return_val_if_fail (qsf_be->params, NULL);
113 params = qsf_be->params;
118 _(
"Level of compression to use: 0 for none, 9 for highest.");
120 _(
"QOF can compress QSF XML files using gzip. "
121 "Note that compression is not used when outputting to STDOUT.");
130 _(
"List of QSF map files to use for this session.");
132 _(
"QOF can convert objects within QSF XML files "
133 "using a map of the changes required.");
141 _(
"Encoding string to use when writing the XML file.");
143 _(
"QSF defaults to UTF-8. Other encodings are supported by "
144 "passing the encoding string in this option.");
152 _(
"Convert deprecated date values to time values.");
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.");
167 qsf_map_prepare_list (GList ** maps)
171 *maps = g_list_prepend (*maps,
"pilot-qsf-GnuCashInvoice.xml");
172 *maps = g_list_prepend (*maps,
"pilot-qsf-gncCustomer.xml");
179 gchar *qsf_time_string;
180 gchar *qsf_enquiry_date;
181 gchar * G_GNUC_UNUSED qsf_time_now;
182 gchar * G_GNUC_UNUSED qsf_time_precision;
184 g_return_if_fail (params != NULL);
195 params->map_ns = NULL;
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);
231 qsf_time_precision =
"%j";
237 g_hash_table_insert (params->qsf_default_hash,
"qsf_enquiry_date",
239 g_hash_table_insert (params->qsf_default_hash,
"qsf_time_now",
241 g_hash_table_insert (params->qsf_default_hash,
"qsf_time_string",
246 (_(
"The selected QSF Object file '%s' requires a "
247 "map but it was not provided."), TRUE);
249 (_(
"When converting XML strings into numbers, an "
250 "overflow has been detected. The QSF object file "
251 "'%s' contains invalid data in a field that is "
252 "meant to hold a number."), TRUE);
256 qsf_determine_file_type (
const gchar * path)
264 if (stat (path, &sbuf) < 0)
268 f = fopen (path,
"a+");
276 if (sbuf.st_size == 0)
278 if (is_our_qsf_object (path))
280 else if (is_qsf_object (path))
282 else if (is_qsf_map (path))
289 const gchar * book_path, gboolean ignore_lock,
290 gboolean create_if_nonexistent)
295 PINFO (
" ignore_lock=%d create_if_nonexistent=%d", ignore_lock,
296 create_if_nonexistent);
297 g_return_if_fail (be != NULL);
298 g_return_if_fail (session);
299 be->
fullpath = g_strdup (book_path);
300 qsf_be = (QSFBackend *) be;
301 g_return_if_fail (qsf_be->params != NULL);
302 qsf_be->fullpath = NULL;
303 if (book_path == NULL)
309 p = strchr (book_path,
':');
312 path = g_strdup (book_path);
313 if (!g_ascii_strncasecmp (path,
"file:", 5))
315 p = g_new0 (gchar, strlen (path) - 5 + 1);
316 strcpy (p, path + 5);
318 qsf_be->fullpath = g_strdup (p);
322 qsf_be->fullpath = g_strdup (book_path);
323 if (create_if_nonexistent)
327 f = fopen (qsf_be->fullpath,
"a+");
333 (_(
"could not write to '%s'. "
334 "That database may be on a read-only file system, "
335 "or you may not have write permission for the "
336 "directory.\n"), TRUE));
346 g_hash_table_destroy (params->qsf_calculate_hash);
347 g_hash_table_destroy (params->qsf_default_hash);
352 xmlFreeNs (params->map_ns);
362 qsf_be = (QSFBackend *) be;
363 g_return_if_fail (qsf_be != NULL);
364 qsf_free_params (qsf_be->params);
365 g_free (qsf_be->fullpath);
366 qsf_be->fullpath = NULL;
377 ent_ref_cb (
QofEntity * ent, gpointer user_data)
387 g_return_if_fail (params);
399 if (reference_setter != NULL)
403 reference_setter (ent, reference);
412 insert_ref_cb (
QofObject * obj, gpointer user_data)
417 g_return_if_fail (params);
426 qsfdoc_to_qofbook (
QsfParam * params)
435 g_return_val_if_fail (params != NULL, FALSE);
436 g_return_val_if_fail (params->
input_doc != NULL, FALSE);
437 g_return_val_if_fail (params->
book != NULL, FALSE);
439 qsf_root = xmlDocGetRootElement (params->
input_doc);
442 qsf_ns = qsf_root->ns;
447 qsf_node_foreach (qsf_root, qsf_book_node_handler, &qiter, params);
449 while (object_list != NULL)
452 object_list = g_list_next (object_list);
459 g_return_val_if_fail (inst != NULL, FALSE);
462 qsf_object_commitCB, params);
472 load_qsf_object (
QofBook * book,
const gchar * fullpath,
475 xmlNodePtr qsf_root, map_root;
476 xmlDocPtr mapDoc, foreign_doc;
477 gchar *map_path, *map_file;
484 qof_error_set_be (params->
be, params->err_nomap);
487 foreign_doc = xmlParseFile (fullpath);
488 if (foreign_doc == NULL)
491 (_(
"There was an error parsing the file '%s'.\n"), TRUE));
495 qsf_root = xmlDocGetRootElement (foreign_doc);
496 params->
qsf_ns = qsf_root->ns;
498 map_path = g_strdup_printf (
"%s/%s", QSF_SCHEMA_DIR, map_file);
501 qof_error_set_be (params->
be, params->err_nomap);
504 mapDoc = xmlParseFile (map_path);
507 qof_error_set_be (params->
be, params->err_nomap);
510 map_root = xmlDocGetRootElement (mapDoc);
511 params->map_ns = map_root->ns;
512 params->
input_doc = qsf_object_convert (mapDoc, qsf_root, params);
513 qsfdoc_to_qofbook (params);
518 load_our_qsf_object (
const gchar * fullpath,
QsfParam * params)
522 params->
input_doc = xmlParseFile (fullpath);
526 (_(
"There was an error parsing the file '%s'."), TRUE));
530 qsf_root = xmlDocGetRootElement (params->
input_doc);
531 params->
qsf_ns = qsf_root->ns;
532 return qsfdoc_to_qofbook (params);
562 g_return_if_fail (be != NULL);
563 g_return_if_fail (book != NULL);
564 qsf_be = (QSFBackend *) be;
565 g_return_if_fail (qsf_be != NULL);
566 g_return_if_fail (qsf_be->fullpath != NULL);
567 g_return_if_fail (qsf_be->params != NULL);
569 (_(
"There was an error parsing the file '%s'."), TRUE);
570 params = qsf_be->params;
572 DEBUG (
" qsf_be->fullpath=%s", qsf_be->fullpath);
573 path = g_strdup (qsf_be->fullpath);
574 f = fopen (path,
"r");
577 (_(
"There was an error reading the file '%s'."), TRUE));
581 result = is_our_qsf_object_be (params);
585 result = load_our_qsf_object (path, params);
587 qof_error_set_be (be, parse_err);
590 else if (is_qsf_object_be (params))
593 result = load_qsf_object (book, path, params);
595 qof_error_set_be (be, parse_err);
606 if (is_qsf_map_be (params))
610 (_(
"The selected file '%s' is a QSF map and cannot "
611 "be opened as a QSF object."), TRUE));
617 qsf_object_sequence (
QofParam * qof_param, gpointer data)
620 GSList *checklist, *result;
622 g_return_if_fail (data != NULL);
628 for (result = checklist; result != NULL; result = result->next)
632 qof_param->param_type))
635 g_slist_free (checklist);
657 qsf_supported_parameters (gpointer type, gpointer user_data)
661 g_return_if_fail (user_data != NULL);
670 qsf_to_kvp_helper (
const char *type_string)
676 if (0 ==
safe_strcmp (QSF_TYPE_BINARY, type_string))
678 if (0 ==
safe_strcmp (QSF_TYPE_GLIST, type_string))
680 if (0 ==
safe_strcmp (QSF_TYPE_FRAME, type_string))
696 return QSF_TYPE_BINARY;
701 return QSF_TYPE_GLIST;
706 return QSF_TYPE_FRAME;
718 qsf_from_kvp_helper (
const gchar * path,
KvpValue * content,
730 g_return_if_fail (params && path && content);
731 n = kvp_value_get_type (content);
746 xmlNewNode (params->
qsf_ns,
747 BAD_CAST qof_param->param_type));
748 xmlNodeAddContent (node,
751 BAD_CAST qof_param->param_name);
756 BAD_CAST kvp_value_to_qof_type_helper (n));
767 qsf_from_kvp_helper, params);
774 PERR (
" unsupported value = %d", kvp_value_get_type (content));
781 qsf_from_coll_cb (
QofEntity * ent, gpointer user_data)
794 BAD_CAST qof_param->param_type));
795 xmlNodeAddContent (node, BAD_CAST qsf_guid);
797 BAD_CAST qof_param->param_name);
803 qof_reference_list_cb (gconstpointer a, gconstpointer b)
812 g_return_val_if_fail ((bb != NULL), 1);
813 g_return_val_if_fail ((aa->
type != NULL), 1);
817 aa->
param->param_name)))
828 if (referenceList == NULL)
830 g_return_val_if_fail (find != NULL, NULL);
834 g_list_find_custom (referenceList, find, qof_reference_list_cb);
835 if (single_ref == NULL)
838 g_list_free (single_ref);
843 reference_list_lookup (gpointer data, gpointer user_data)
850 xmlNodePtr node, object_node;
862 starter->
type = g_strdup (ent->e_type);
863 starter->
param = ref_param;
866 reference = qof_reference_lookup (copy_list, starter);
868 if (reference != NULL)
870 if ((ref_param->param_getfcn == NULL)
871 || (ref_param->param_setfcn == NULL))
873 ref_name = g_strdup (reference->
param->param_name);
875 xmlAddChild (object_node,
876 xmlNewNode (ns, BAD_CAST QOF_TYPE_GUID));
878 xmlNodeAddContent (node, BAD_CAST qsf_guid);
884 ent = (
QofEntity *) ref_param->param_getfcn (ent, ref_param);
891 xmlAddChild (object_node,
892 xmlNewNode (ns, BAD_CAST QOF_TYPE_GUID));
895 xmlNodeAddContent (node, BAD_CAST qsf_guid);
897 BAD_CAST ref_param->param_name);
906 qsf_entity_foreach (
QofEntity * ent, gpointer data)
909 GSList *param_list, *supported;
911 xmlNodePtr node, object_node;
913 gchar *string_buffer;
923 g_return_if_fail (data != NULL);
925 param_count = ++params->
count;
933 BAD_CAST ent->e_type);
934 string_buffer = g_strdup_printf (
"%i", param_count);
936 BAD_CAST string_buffer);
937 g_free (string_buffer);
939 while (param_list != NULL)
941 qof_param = (
QofParam *) param_list->data;
942 g_return_if_fail (qof_param != NULL);
943 if (0 ==
safe_strcmp (qof_param->param_type, QOF_TYPE_GUID))
948 node = xmlAddChild (object_node, xmlNewNode (ns, BAD_CAST
951 string_buffer = g_strdup (cm_sa);
952 xmlNodeAddContent (node, BAD_CAST string_buffer);
955 g_free (string_buffer);
962 g_list_foreach (ref, reference_list_lookup, params);
966 qsf_coll = qof_param->param_getfcn (ent, qof_param);
975 param_list = g_slist_next (param_list);
982 (
QofEntity *) qof_param->param_getfcn (ent, qof_param);
985 param_list = g_slist_next (param_list);
988 node = xmlAddChild (object_node, xmlNewNode (ns, BAD_CAST
989 qof_param->param_type));
992 string_buffer = g_strdup (cm_sa);
993 xmlNodeAddContent (node, BAD_CAST string_buffer);
995 qof_param->param_name);
996 xmlNewProp (node, BAD_CAST
"name",
997 BAD_CAST choice_ent->e_type);
998 g_free (string_buffer);
999 param_list = g_slist_next (param_list);
1002 if (0 ==
safe_strcmp (qof_param->param_type, QOF_TYPE_KVP))
1005 (
KvpFrame *) qof_param->param_getfcn (ent, qof_param);
1012 if ((qof_param->param_setfcn != NULL)
1013 && (qof_param->param_getfcn != NULL))
1016 supported != NULL; supported = g_slist_next (supported))
1018 if (0 ==
safe_strcmp ((
const gchar *) supported->data,
1019 (
const gchar *) qof_param->param_type))
1021 node = xmlAddChild (object_node,
1022 xmlNewNode (ns, BAD_CAST qof_param->param_type));
1026 xmlNodeAddContent (node, BAD_CAST string_buffer);
1028 qof_param->param_name);
1029 g_free (string_buffer);
1033 param_list = g_slist_next (param_list);
1038 qsf_foreach_obj_type (
QofObject * qsf_obj, gpointer data)
1044 g_return_if_fail (data != NULL);
1047 if ((qsf_obj->
create == NULL) || (qsf_obj->
foreach == NULL))
1049 PINFO (
" qsf_obj QOF support failed %s", qsf_obj->e_type);
1054 book = params->
book;
1056 g_slist_foreach (support, qsf_supported_parameters, params);
1067 xmlNodePtr top_node, node;
1070 const GUID *book_guid;
1072 g_return_val_if_fail (book != NULL, NULL);
1073 params->
book = book;
1079 xmlDocSetRootElement (doc, top_node);
1082 params->
qsf_ns = top_node->ns;
1099 write_qsf_from_book (
const gchar *path,
QofBook * book,
1107 qsf_doc = qofbook_to_qsf (book, params);
1109 PINFO (
" use_gz_level=%" G_GINT64_FORMAT
" encoding=%s",
1113 g_return_if_fail (qsf_is_valid
1116 xmlSaveFormatFileEnc (path, qsf_doc, params->
encoding, 1);
1117 if (write_result < 0)
1120 (_(
"Could not write to '%s'. Check that you have "
1121 "permission to write to this file and that there is "
1122 "sufficient space to create it."), TRUE));
1125 qof_object_mark_clean (book);
1133 qsf_doc = qofbook_to_qsf (book, params);
1134 g_return_if_fail (qsf_is_valid
1136 PINFO (
" use_gz_level=%" G_GINT64_FORMAT
" encoding=%s",
1138 xmlSaveFormatFileEnc (
"-", qsf_doc, params->
encoding, 1);
1139 fprintf (stdout,
"\n");
1140 qof_object_mark_clean (book);
1150 qsf_be = (QSFBackend *) be;
1151 params = qsf_be->params;
1153 if (!qsf_be->fullpath || (*qsf_be->fullpath ==
'\0'))
1155 write_qsf_to_stdout (book, params);
1158 path = strdup (qsf_be->fullpath);
1159 write_qsf_from_book (path, book, params);
1177 cm_i64 = strtoll (content, &tail, 0);
1180 return kvp_value_new_gint64 (cm_i64);
1187 cm_double = strtod (content, &tail);
1189 return kvp_value_new_double (cm_double);
1195 return kvp_value_new_numeric (cm_numeric);
1200 return kvp_value_new_string (content);
1205 cm_guid = g_new0 (
GUID, 1);
1207 return kvp_value_new_guid (cm_guid);
1220 retval = kvp_value_new_time (qt);
1226 PERR (
" failed to parse date");
1252 qsf_object_commitCB (gpointer key, gpointer value, gpointer data)
1259 QofBook * G_GNUC_UNUSED targetBook;
1260 const gchar *qof_type, *parameter_name;
1266 gboolean cm_boolean;
1269 gchar cm_char, (*char_getter) (xmlNodePtr);
1276 void (*string_setter) (
QofEntity *,
const gchar *);
1279 void (*double_setter) (
QofEntity *, gdouble);
1280 void (*boolean_setter) (
QofEntity *, gboolean);
1281 void (*i32_setter) (
QofEntity *, gint32);
1282 void (*i64_setter) (
QofEntity *, gint64);
1283 void (*char_setter) (
QofEntity *, gchar);
1285 g_return_if_fail (data && value && key);
1287 node = (xmlNodePtr) value;
1288 parameter_name = (
const gchar *) key;
1289 qof_type = (gchar *) node->name;
1291 targetBook = params->
book;
1303 string_setter = (void (*)(
QofEntity *,
const gchar *)) cm_setter;
1304 if (string_setter != NULL)
1307 string_setter (qsf_ent, (gchar *) xmlNodeGetContent (node));
1314 if (time_setter != NULL)
1320 (
const gchar*) xmlNodeGetContent (node),
1326 time_setter (qsf_ent, qt);
1331 PERR (
" failed to parse date string");
1334 if ((
safe_strcmp (qof_type, QOF_TYPE_NUMERIC) == 0) ||
1339 tmp = (
char *) xmlNodeGetContent (node);
1342 if (numeric_setter != NULL)
1345 numeric_setter (qsf_ent, cm_numeric);
1351 cm_guid = g_new0 (
GUID, 1);
1356 _(
"The selected QSF object file '%s' contains one or "
1357 "more invalid GUIDs. The file cannot be processed - "
1358 "please check the source of the file and try again."),
1360 PINFO (
" string to guid conversion failed for %s:%s:%s",
1361 xmlNodeGetContent (node), obj_type, qof_type);
1366 if (0 ==
safe_strcmp (QOF_PARAM_GUID, reference_type))
1386 (gint32) strtol ((
char *) xmlNodeGetContent (node), &tail, 0);
1389 i32_setter = (void (*)(
QofEntity *, gint32)) cm_setter;
1390 if (i32_setter != NULL)
1393 i32_setter (qsf_ent, cm_i32);
1398 qof_error_set_be (params->
be, params->err_overflow);
1403 cm_i64 = strtoll ((gchar *) xmlNodeGetContent (node), &tail, 0);
1406 i64_setter = (void (*)(
QofEntity *, gint64)) cm_setter;
1407 if (i64_setter != NULL)
1410 i64_setter (qsf_ent, cm_i64);
1415 qof_error_set_be (params->
be, params->err_overflow);
1420 cm_double = strtod ((gchar *) xmlNodeGetContent (node), &tail);
1423 double_setter = (void (*)(
QofEntity *, gdouble)) cm_setter;
1424 if (double_setter != NULL)
1427 double_setter (qsf_ent, cm_double);
1432 if (
safe_strcmp (qof_type, QOF_TYPE_BOOLEAN) == 0)
1439 boolean_setter = (void (*)(
QofEntity *, gboolean)) cm_setter;
1440 if (boolean_setter != NULL)
1443 boolean_setter (qsf_ent, cm_boolean);
1450 qsf_to_kvp_helper ((gchar *)
1456 string_to_kvp_value ((gchar *) xmlNodeGetContent (node),
1458 cm_kvp = (
KvpFrame *) cm_param->param_getfcn (qsf_ent, cm_param);
1471 qsf_coll = cm_param->param_getfcn (qsf_ent, cm_param);
1473 cm_guid = g_new0 (
GUID, 1);
1478 _(
"The selected QSF object file '%s' contains one or "
1479 "more invalid 'collect' values. The file cannot be processed - "
1480 "please check the source of the file and try again."),
1482 PINFO (
" string to guid collect failed for %s",
1483 xmlNodeGetContent (node));
1491 reference->
type = g_strdup (qsf_ent->e_type);
1493 reference->
ent_guid = &qsf_ent->guid;
1495 copy_param->param_name = g_strdup (cm_param->param_name);
1496 copy_param->param_type = g_strdup (cm_param->param_type);
1497 reference->
param = copy_param;
1503 char_getter = (gchar (*)(xmlNodePtr)) xmlNodeGetContent;
1504 cm_char = char_getter (node);
1505 char_setter = (void (*)(
QofEntity *, gchar)) cm_setter;
1506 if (char_setter != NULL)
1509 char_setter (qsf_ent, cm_char);
1516 qsf_backend_new (
void)
1521 qsf_be = g_new0 (QSFBackend, 1);
1523 qof_backend_init (be);
1524 qsf_be->params = g_new0 (
QsfParam, 1);
1525 qsf_be->params->be = be;
1526 qsf_param_init (qsf_be->params);
1527 qsf_be->be.session_begin = qsf_session_begin;
1529 be->session_end = qsf_session_end;
1530 be->destroy_backend = qsf_destroy_backend;
1531 be->load = qsf_file_type;
1536 be->rollback = NULL;
1538 be->compile_query = NULL;
1539 be->free_query = NULL;
1540 be->run_query = NULL;
1543 be->events_pending = NULL;
1544 be->process_events = NULL;
1546 be->sync = qsf_write_file;
1548 be->load_config = qsf_load_config;
1549 be->get_config = qsf_get_config;
1551 qsf_be->fullpath = NULL;
1571 bindtextdomain (PACKAGE, LOCALE_DIR);