00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "config.h"
00025 #include <errno.h>
00026 #include <sys/stat.h>
00027 #include <glib.h>
00028 #include <libxml/xmlmemory.h>
00029 #include <libxml/tree.h>
00030 #include <libxml/parser.h>
00031 #include <libxml/xmlschemas.h>
00032 #include "qof.h"
00033 #include "qofobject-p.h"
00034 #include "qof-backend-qsf.h"
00035 #include "qsf-xml.h"
00036 #include "kvputil-p.h"
00037
00038 #define QSF_TYPE_BINARY "binary"
00039 #define QSF_TYPE_GLIST "glist"
00040 #define QSF_TYPE_FRAME "frame"
00041
00042 static QofLogModule log_module = QOF_MOD_QSF;
00043
00044 static void qsf_object_commitCB (gpointer key, gpointer value,
00045 gpointer data);
00046
00047 struct QSFBackend_s
00048 {
00049 QofBackend be;
00050 QsfParam *params;
00051 gchar *fullpath;
00052 };
00053
00054 typedef struct QSFBackend_s QSFBackend;
00055
00056 static void
00057 option_cb (QofBackendOption * option, gpointer data)
00058 {
00059 QsfParam *params;
00060
00061 params = (QsfParam *) data;
00062 g_return_if_fail (params);
00063 if (0 == safe_strcmp (QSF_COMPRESS, option->option_name))
00064 {
00065 params->use_gz_level = (*(gint64 *) option->value);
00066 PINFO (" compression=%" G_GINT64_FORMAT, params->use_gz_level);
00067 }
00068 if (0 == safe_strcmp (QSF_MAP_FILES, option->option_name))
00069 {
00070 params->map_files = g_list_copy ((GList *) option->value);
00071 }
00072 if (0 == safe_strcmp (QSF_ENCODING, option->option_name))
00073 {
00074 params->encoding = g_strdup (option->value);
00075 PINFO (" encoding=%s", params->encoding);
00076 }
00077 if (0 == safe_strcmp (QSF_DATE_CONVERT, option->option_name))
00078 {
00079 params->convert = (*(double *) option->value);
00080 if (params->convert > 0)
00081 PINFO (" converting date into time on file write.");
00082 }
00083 }
00084
00085 static void
00086 qsf_load_config (QofBackend * be, KvpFrame * config)
00087 {
00088 QSFBackend *qsf_be;
00089 QsfParam *params;
00090
00091 ENTER (" ");
00092 qsf_be = (QSFBackend *) be;
00093 g_return_if_fail (qsf_be->params);
00094 params = qsf_be->params;
00095 qof_backend_option_foreach (config, option_cb, params);
00096 LEAVE (" ");
00097 }
00098
00099 static KvpFrame *
00100 qsf_get_config (QofBackend * be)
00101 {
00102 QofBackendOption *option;
00103 QSFBackend *qsf_be;
00104 QsfParam *params;
00105
00106 if (!be)
00107 {
00108 return NULL;
00109 }
00110 ENTER (" ");
00111 qsf_be = (QSFBackend *) be;
00112 g_return_val_if_fail (qsf_be->params, NULL);
00113 params = qsf_be->params;
00114 qof_backend_prepare_frame (be);
00115 option = g_new0 (QofBackendOption, 1);
00116 option->option_name = QSF_COMPRESS;
00117 option->description =
00118 _("Level of compression to use: 0 for none, 9 for highest.");
00119 option->tooltip =
00120 _("QOF can compress QSF XML files using gzip. "
00121 "Note that compression is not used when outputting to STDOUT.");
00122 option->type = KVP_TYPE_GINT64;
00123
00124 option->value = (gpointer) & params->use_gz_level;
00125 qof_backend_prepare_option (be, option);
00126 g_free (option);
00127 option = g_new0 (QofBackendOption, 1);
00128 option->option_name = QSF_MAP_FILES;
00129 option->description =
00130 _("List of QSF map files to use for this session.");
00131 option->tooltip =
00132 _("QOF can convert objects within QSF XML files "
00133 "using a map of the changes required.");
00134 option->type = KVP_TYPE_GLIST;
00135 option->value = (gpointer) params->map_files;
00136 qof_backend_prepare_option (be, option);
00137 g_free (option);
00138 option = g_new0 (QofBackendOption, 1);
00139 option->option_name = QSF_ENCODING;
00140 option->description =
00141 _("Encoding string to use when writing the XML file.");
00142 option->tooltip =
00143 _("QSF defaults to UTF-8. Other encodings are supported by "
00144 "passing the encoding string in this option.");
00145 option->type = KVP_TYPE_STRING;
00146 option->value = (gpointer) params->encoding;
00147 qof_backend_prepare_option (be, option);
00148 g_free (option);
00149 option = g_new0 (QofBackendOption, 1);
00150 option->option_name = QSF_DATE_CONVERT;
00151 option->description =
00152 _("Convert deprecated date values to time values.");
00153 option->tooltip =
00154 _("Applications that support the new QOF time format "
00155 "need to enable this option to convert older date values into time. "
00156 "Applications that still use date should not set this option "
00157 "until time values are supported.");
00158 option->type = KVP_TYPE_GINT64;
00159 option->value = ¶ms->convert;
00160 qof_backend_prepare_option (be, option);
00161 g_free (option);
00162 LEAVE (" ");
00163 return qof_backend_complete_frame (be);
00164 }
00165
00166 GList **
00167 qsf_map_prepare_list (GList ** maps)
00168 {
00169
00171 *maps = g_list_prepend (*maps, "pilot-qsf-GnuCashInvoice.xml");
00172 *maps = g_list_prepend (*maps, "pilot-qsf-gncCustomer.xml");
00173 return maps;
00174 }
00175
00176 static void
00177 qsf_param_init (QsfParam * params)
00178 {
00179 gchar *qsf_time_string;
00180 gchar *qsf_enquiry_date;
00181 gchar *qsf_time_now;
00182 gchar *qsf_time_precision;
00183
00184 g_return_if_fail (params != NULL);
00185 params->count = 0;
00186 params->convert = 1;
00187 params->use_gz_level = 0;
00188 params->supported_types = NULL;
00189 params->file_type = QSF_UNDEF;
00190 params->qsf_ns = NULL;
00191 params->output_doc = NULL;
00192 params->output_node = NULL;
00193 params->lister = NULL;
00194 params->full_kvp_path = NULL;
00195 params->map_ns = NULL;
00196 params->map_files = NULL;
00197 params->map_path = NULL;
00198 params->encoding = "UTF-8";
00199 params->qsf_object_list = NULL;
00200 params->qsf_parameter_hash =
00201 g_hash_table_new (g_str_hash, g_str_equal);
00202 params->qsf_default_hash = g_hash_table_new (g_str_hash, g_str_equal);
00203 params->qsf_define_hash = g_hash_table_new (g_str_hash, g_str_equal);
00204 params->qsf_calculate_hash =
00205 g_hash_table_new (g_str_hash, g_str_equal);
00206 params->referenceList = NULL;
00207 params->supported_types =
00208 g_slist_append (params->supported_types, QOF_TYPE_STRING);
00209 params->supported_types =
00210 g_slist_append (params->supported_types, QOF_TYPE_GUID);
00211 params->supported_types =
00212 g_slist_append (params->supported_types, QOF_TYPE_BOOLEAN);
00213 params->supported_types =
00214 g_slist_append (params->supported_types, QOF_TYPE_NUMERIC);
00215 params->supported_types =
00216 g_slist_append (params->supported_types, QOF_TYPE_TIME);
00217 params->supported_types =
00218 g_slist_append (params->supported_types, QOF_TYPE_INT32);
00219 params->supported_types =
00220 g_slist_append (params->supported_types, QOF_TYPE_INT64);
00221 params->supported_types =
00222 g_slist_append (params->supported_types, QOF_TYPE_DOUBLE);
00223 params->supported_types =
00224 g_slist_append (params->supported_types, QOF_TYPE_CHAR);
00225 params->supported_types =
00226 g_slist_append (params->supported_types, QOF_TYPE_KVP);
00227 params->supported_types =
00228 g_slist_append (params->supported_types, QOF_TYPE_COLLECT);
00229 params->supported_types =
00230 g_slist_append (params->supported_types, QOF_TYPE_CHOICE);
00231 qsf_time_precision = "%j";
00232 qsf_enquiry_date = qof_time_stamp_now ();
00233 qsf_time_string = qof_date_print (qof_date_get_current(),
00234 QOF_DATE_FORMAT_ISO);
00235 qsf_time_now = qof_time_stamp_now ();
00236
00237 g_hash_table_insert (params->qsf_default_hash, "qsf_enquiry_date",
00238 qsf_enquiry_date);
00239 g_hash_table_insert (params->qsf_default_hash, "qsf_time_now",
00240 qof_time_get_current());
00241 g_hash_table_insert (params->qsf_default_hash, "qsf_time_string",
00242 qsf_time_string);
00243
00244 params->map_files = *qsf_map_prepare_list (¶ms->map_files);
00245 params->err_nomap = qof_error_register
00246 (_("The selected QSF Object file '%s' requires a "
00247 "map but it was not provided."), TRUE);
00248 params->err_overflow = qof_error_register
00249 (_("When converting XML strings into numbers, an "
00250 "overflow has been detected. The QSF object file "
00251 "'%s' contains invalid data in a field that is "
00252 "meant to hold a number."), TRUE);
00253 }
00254
00255 static gboolean
00256 qsf_determine_file_type (const gchar * path)
00257 {
00258 struct stat sbuf;
00259
00260 if (!path)
00261 return TRUE;
00262 if (0 == safe_strcmp (path, QOF_STDOUT))
00263 return TRUE;
00264 if (stat (path, &sbuf) < 0)
00265 {
00266
00267 FILE * f;
00268 f = fopen (path, "a+");
00269 if (f)
00270 {
00271 fclose (f);
00272 return TRUE;
00273 }
00274 return FALSE;
00275 }
00276 if (sbuf.st_size == 0)
00277 return TRUE;
00278 if (is_our_qsf_object (path))
00279 return TRUE;
00280 else if (is_qsf_object (path))
00281 return TRUE;
00282 else if (is_qsf_map (path))
00283 return TRUE;
00284 return FALSE;
00285 }
00286
00287 static void
00288 qsf_session_begin (QofBackend * be, QofSession * session,
00289 const gchar * book_path, gboolean ignore_lock,
00290 gboolean create_if_nonexistent)
00291 {
00292 QSFBackend *qsf_be;
00293 gchar *p, *path;
00294
00295 PINFO (" ignore_lock=%d create_if_nonexistent=%d", ignore_lock,
00296 create_if_nonexistent);
00297 g_return_if_fail (be != NULL);
00298 g_return_if_fail (session);
00299 be->fullpath = g_strdup (book_path);
00300 qsf_be = (QSFBackend *) be;
00301 g_return_if_fail (qsf_be->params != NULL);
00302 qsf_be->fullpath = NULL;
00303 if (book_path == NULL)
00304 {
00305
00306 qof_error_set_be (be, QOF_SUCCESS);
00307 return;
00308 }
00309 p = strchr (book_path, ':');
00310 if (p)
00311 {
00312 path = g_strdup (book_path);
00313 if (!g_ascii_strncasecmp (path, "file:", 5))
00314 {
00315 p = g_new0 (gchar, strlen (path) - 5 + 1);
00316 strcpy (p, path + 5);
00317 }
00318 qsf_be->fullpath = g_strdup (p);
00319 g_free (path);
00320 }
00321 else
00322 qsf_be->fullpath = g_strdup (book_path);
00323 if (create_if_nonexistent)
00324 {
00325 FILE *f;
00326
00327 f = fopen (qsf_be->fullpath, "a+");
00328 if (f)
00329 fclose (f);
00330 else
00331 {
00332 qof_error_set_be (be, qof_error_register
00333 (_("could not write to '%s'. "
00334 "That database may be on a read-only file system, "
00335 "or you may not have write permission for the "
00336 "directory.\n"), TRUE));
00337 return;
00338 }
00339 }
00340 qof_error_set_be (be, QOF_SUCCESS);
00341 }
00342
00343 static void
00344 qsf_free_params (QsfParam * params)
00345 {
00346 g_hash_table_destroy (params->qsf_calculate_hash);
00347 g_hash_table_destroy (params->qsf_default_hash);
00348 if (params->referenceList)
00349 g_list_free (params->referenceList);
00350 g_slist_free (params->supported_types);
00351 if (params->map_ns)
00352 xmlFreeNs (params->map_ns);
00353 if (params->output_doc)
00354 xmlFreeDoc (params->output_doc);
00355 }
00356
00357 static void
00358 qsf_session_end (QofBackend * be)
00359 {
00360 QSFBackend *qsf_be;
00361
00362 qsf_be = (QSFBackend *) be;
00363 g_return_if_fail (qsf_be != NULL);
00364 qsf_free_params (qsf_be->params);
00365 g_free (qsf_be->fullpath);
00366 qsf_be->fullpath = NULL;
00367 xmlCleanupParser ();
00368 }
00369
00370 static void
00371 qsf_destroy_backend (QofBackend * be)
00372 {
00373 g_free (be);
00374 }
00375
00376 static void
00377 ent_ref_cb (QofEntity * ent, gpointer user_data)
00378 {
00379 QsfParam *params;
00380 QofEntityReference *ref;
00381 void (*reference_setter) (QofEntity *, QofEntity *);
00382 QofEntity *reference;
00383 QofCollection *coll;
00384 QofIdType type;
00385
00386 params = (QsfParam *) user_data;
00387 g_return_if_fail (params);
00388 while (params->referenceList)
00389 {
00390 ref = (QofEntityReference *) params->referenceList->data;
00391 if (qof_object_is_choice (ent->e_type))
00392 type = ref->choice_type;
00393 else
00394 type = ref->type;
00395 coll = qof_book_get_collection (params->book, type);
00396 reference = qof_collection_lookup_entity (coll, ref->ref_guid);
00397 reference_setter =
00398 (void (*)(QofEntity *, QofEntity *)) ref->param->param_setfcn;
00399 if (reference_setter != NULL)
00400 {
00401 qof_util_param_edit ((QofInstance *) ent, ref->param);
00402 qof_util_param_edit ((QofInstance *) reference, ref->param);
00403 reference_setter (ent, reference);
00404 qof_util_param_commit ((QofInstance *) ent, ref->param);
00405 qof_util_param_commit ((QofInstance *) reference, ref->param);
00406 }
00407 params->referenceList = g_list_next (params->referenceList);
00408 }
00409 }
00410
00411 static void
00412 insert_ref_cb (QofObject * obj, gpointer user_data)
00413 {
00414 QsfParam *params;
00415
00416 params = (QsfParam *) user_data;
00417 g_return_if_fail (params);
00418 qof_object_foreach (obj->e_type, params->book, ent_ref_cb, params);
00419 }
00420
00421
00422
00423
00424
00425 static gboolean
00426 qsfdoc_to_qofbook (QsfParam * params)
00427 {
00428 QofInstance *inst;
00429 struct QsfNodeIterate qiter;
00430 QofBook *book;
00431 GList *object_list;
00432 xmlNodePtr qsf_root;
00433 xmlNsPtr qsf_ns;
00434
00435 g_return_val_if_fail (params != NULL, FALSE);
00436 g_return_val_if_fail (params->input_doc != NULL, FALSE);
00437 g_return_val_if_fail (params->book != NULL, FALSE);
00438 g_return_val_if_fail (params->file_type == OUR_QSF_OBJ, FALSE);
00439 qsf_root = xmlDocGetRootElement (params->input_doc);
00440 if (!qsf_root)
00441 return FALSE;
00442 qsf_ns = qsf_root->ns;
00443 qiter.ns = qsf_ns;
00444 book = params->book;
00445 params->referenceList =
00446 (GList *) qof_book_get_data (book, ENTITYREFERENCE);
00447 qsf_node_foreach (qsf_root, qsf_book_node_handler, &qiter, params);
00448 object_list = g_list_copy (params->qsf_object_list);
00449 while (object_list != NULL)
00450 {
00451 params->object_set = object_list->data;
00452 object_list = g_list_next (object_list);
00453 params->qsf_parameter_hash = params->object_set->parameters;
00454 if (!qof_class_is_registered (params->object_set->object_type))
00455 continue;
00456 inst =
00457 (QofInstance *) qof_object_new_instance (params->object_set->
00458 object_type, book);
00459 g_return_val_if_fail (inst != NULL, FALSE);
00460 params->qsf_ent = &inst->entity;
00461 g_hash_table_foreach (params->qsf_parameter_hash,
00462 qsf_object_commitCB, params);
00463 }
00464 qof_object_foreach_type (insert_ref_cb, params);
00465 qof_book_set_data (book, ENTITYREFERENCE, params->referenceList);
00466 return TRUE;
00467 }
00468
00469
00470
00471 static gboolean
00472 load_qsf_object (QofBook * book, const gchar * fullpath,
00473 QsfParam * params)
00474 {
00475 xmlNodePtr qsf_root, map_root;
00476 xmlDocPtr mapDoc, foreign_doc;
00477 gchar *map_path, *map_file;
00478
00479 map_file = params->map_path;
00480 mapDoc = NULL;
00481
00482 if (!map_file)
00483 {
00484 qof_error_set_be (params->be, params->err_nomap);
00485 return FALSE;
00486 }
00487 foreign_doc = xmlParseFile (fullpath);
00488 if (foreign_doc == NULL)
00489 {
00490 qof_error_set_be (params->be, qof_error_register
00491 (_("There was an error parsing the file '%s'.\n"), TRUE));
00492 return FALSE;
00493 }
00494 qsf_root = NULL;
00495 qsf_root = xmlDocGetRootElement (foreign_doc);
00496 params->qsf_ns = qsf_root->ns;
00497 params->book = book;
00498 map_path = g_strdup_printf ("%s/%s", QSF_SCHEMA_DIR, map_file);
00499 if (!map_path)
00500 {
00501 qof_error_set_be (params->be, params->err_nomap);
00502 return FALSE;
00503 }
00504 mapDoc = xmlParseFile (map_path);
00505 if (!mapDoc)
00506 {
00507 qof_error_set_be (params->be, params->err_nomap);
00508 return FALSE;
00509 }
00510 map_root = xmlDocGetRootElement (mapDoc);
00511 params->map_ns = map_root->ns;
00512 params->input_doc = qsf_object_convert (mapDoc, qsf_root, params);
00513 qsfdoc_to_qofbook (params);
00514 return TRUE;
00515 }
00516
00517 static gboolean
00518 load_our_qsf_object (const gchar * fullpath, QsfParam * params)
00519 {
00520 xmlNodePtr qsf_root;
00521
00522 params->input_doc = xmlParseFile (fullpath);
00523 if (params->input_doc == NULL)
00524 {
00525 qof_error_set_be (params->be, qof_error_register
00526 (_("There was an error parsing the file '%s'."), TRUE));
00527 return FALSE;
00528 }
00529 qsf_root = NULL;
00530 qsf_root = xmlDocGetRootElement (params->input_doc);
00531 params->qsf_ns = qsf_root->ns;
00532 return qsfdoc_to_qofbook (params);
00533 }
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552 static void
00553 qsf_file_type (QofBackend * be, QofBook * book)
00554 {
00555 QSFBackend *qsf_be;
00556 QofErrorId parse_err;
00557 QsfParam *params;
00558 FILE *f;
00559 gchar *path;
00560 gboolean result;
00561
00562 g_return_if_fail (be != NULL);
00563 g_return_if_fail (book != NULL);
00564 qsf_be = (QSFBackend *) be;
00565 g_return_if_fail (qsf_be != NULL);
00566 g_return_if_fail (qsf_be->fullpath != NULL);
00567 g_return_if_fail (qsf_be->params != NULL);
00568 parse_err = qof_error_register
00569 (_("There was an error parsing the file '%s'."), TRUE);
00570 params = qsf_be->params;
00571 params->book = book;
00572 DEBUG (" qsf_be->fullpath=%s", qsf_be->fullpath);
00573 path = g_strdup (qsf_be->fullpath);
00574 f = fopen (path, "r");
00575 if (!f)
00576 qof_error_set_be (be, qof_error_register
00577 (_("There was an error reading the file '%s'."), TRUE));
00578 else
00579 fclose (f);
00580 params->filepath = g_strdup (path);
00581 result = is_our_qsf_object_be (params);
00582 if (result)
00583 {
00584 params->file_type = OUR_QSF_OBJ;
00585 result = load_our_qsf_object (path, params);
00586 if (!result)
00587 qof_error_set_be (be, parse_err);
00588 return;
00589 }
00590 else if (is_qsf_object_be (params))
00591 {
00592 params->file_type = IS_QSF_OBJ;
00593 result = load_qsf_object (book, path, params);
00594 if (!result)
00595 qof_error_set_be (be, parse_err);
00596 return;
00597 }
00598 if (qof_error_check_be (be) == params->err_nomap)
00599 {
00600
00601 params->file_type = IS_QSF_OBJ;
00602 result = TRUE;
00603 }
00604 if (result == FALSE)
00605 {
00606 if (is_qsf_map_be (params))
00607 {
00608 params->file_type = IS_QSF_MAP;
00609 qof_error_set_be (be, qof_error_register
00610 (_("The selected file '%s' is a QSF map and cannot "
00611 "be opened as a QSF object."), TRUE));
00612 }
00613 }
00614 }
00615
00616 static void
00617 qsf_object_sequence (QofParam * qof_param, gpointer data)
00618 {
00619 QsfParam *params;
00620 GSList *checklist, *result;
00621
00622 g_return_if_fail (data != NULL);
00623 params = (QsfParam *) data;
00624 result = NULL;
00625 checklist = NULL;
00626 params->knowntype = FALSE;
00627 checklist = g_slist_copy (params->supported_types);
00628 for (result = checklist; result != NULL; result = result->next)
00629 {
00630 if (0 ==
00631 safe_strcmp ((QofIdType) result->data,
00632 qof_param->param_type))
00633 params->knowntype = TRUE;
00634 }
00635 g_slist_free (checklist);
00636 if (0 == safe_strcmp (qof_param->param_type, params->qof_type))
00637 {
00638 params->qsf_sequence =
00639 g_slist_append (params->qsf_sequence, qof_param);
00640 params->knowntype = TRUE;
00641 }
00642
00643 if (0 == safe_strcmp (params->qof_type, QOF_TYPE_GUID)
00644 && (params->knowntype == FALSE))
00645 {
00646 params->qsf_sequence =
00647 g_slist_append (params->qsf_sequence, qof_param);
00648 params->knowntype = TRUE;
00649 }
00650 }
00651
00652
00653
00654
00655
00656 static void
00657 qsf_supported_parameters (gpointer type, gpointer user_data)
00658 {
00659 QsfParam *params;
00660
00661 g_return_if_fail (user_data != NULL);
00662 params = (QsfParam *) user_data;
00663 params->qof_type = (QofIdType) type;
00664 params->knowntype = FALSE;
00665 qof_class_param_foreach (params->qof_obj_type, qsf_object_sequence,
00666 params);
00667 }
00668
00669 static KvpValueType
00670 qsf_to_kvp_helper (const char *type_string)
00671 {
00672 KvpValueType kvt;
00673 kvt = qof_id_to_kvp_value_type (type_string);
00674 if (kvt != 0)
00675 return kvt;
00676 if (0 == safe_strcmp (QSF_TYPE_BINARY, type_string))
00677 return KVP_TYPE_BINARY;
00678 if (0 == safe_strcmp (QSF_TYPE_GLIST, type_string))
00679 return KVP_TYPE_GLIST;
00680 if (0 == safe_strcmp (QSF_TYPE_FRAME, type_string))
00681 return KVP_TYPE_FRAME;
00682 return 0;
00683 }
00684
00685 static QofIdTypeConst
00686 kvp_value_to_qof_type_helper (KvpValueType n)
00687 {
00688 QofIdTypeConst qtc;
00689 qtc = kvp_value_type_to_qof_id (n);
00690 if (qtc)
00691 return qtc;
00692 switch (n)
00693 {
00694 case KVP_TYPE_BINARY:
00695 {
00696 return QSF_TYPE_BINARY;
00697 break;
00698 }
00699 case KVP_TYPE_GLIST:
00700 {
00701 return QSF_TYPE_GLIST;
00702 break;
00703 }
00704 case KVP_TYPE_FRAME:
00705 {
00706 return QSF_TYPE_FRAME;
00707 break;
00708 }
00709 default:
00710 {
00711 return NULL;
00712 }
00713 }
00714 }
00715
00716
00717 static void
00718 qsf_from_kvp_helper (const gchar * path, KvpValue * content,
00719 gpointer data)
00720 {
00721 QsfParam *params;
00722 QofParam *qof_param;
00723 xmlNodePtr node;
00724 KvpValueType n;
00725 gchar *full_path;
00726
00727 params = (QsfParam *) data;
00728 qof_param = params->qof_param;
00729 full_path = NULL;
00730 g_return_if_fail (params && path && content);
00731 n = kvp_value_get_type (content);
00732 switch (n)
00733 {
00734 case KVP_TYPE_GINT64:
00735 case KVP_TYPE_DOUBLE:
00736 case KVP_TYPE_NUMERIC:
00737 case KVP_TYPE_STRING:
00738 case KVP_TYPE_GUID:
00739 case KVP_TYPE_TIME :
00740 case KVP_TYPE_BOOLEAN :
00741 case KVP_TYPE_BINARY:
00742 case KVP_TYPE_GLIST:
00743 {
00744 node =
00745 xmlAddChild (params->output_node,
00746 xmlNewNode (params->qsf_ns,
00747 BAD_CAST qof_param->param_type));
00748 xmlNodeAddContent (node,
00749 BAD_CAST kvp_value_to_bare_string (content));
00750 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE,
00751 BAD_CAST qof_param->param_name);
00752 full_path =
00753 g_strconcat (params->full_kvp_path, "/", path, NULL);
00754 xmlNewProp (node, BAD_CAST QSF_OBJECT_KVP, BAD_CAST full_path);
00755 xmlNewProp (node, BAD_CAST QSF_OBJECT_VALUE,
00756 BAD_CAST kvp_value_to_qof_type_helper (n));
00757 break;
00758 }
00759 case KVP_TYPE_FRAME:
00760 {
00761 if (!params->full_kvp_path)
00762 params->full_kvp_path = g_strdup (path);
00763 else
00764 params->full_kvp_path = g_strconcat (params->full_kvp_path,
00765 "/", path, NULL);
00766 kvp_frame_for_each_slot (kvp_value_get_frame (content),
00767 qsf_from_kvp_helper, params);
00768 g_free (params->full_kvp_path);
00769 params->full_kvp_path = NULL;
00770 break;
00771 }
00772 default:
00773 {
00774 PERR (" unsupported value = %d", kvp_value_get_type (content));
00775 break;
00776 }
00777 }
00778 }
00779
00780 static void
00781 qsf_from_coll_cb (QofEntity * ent, gpointer user_data)
00782 {
00783 QsfParam *params;
00784 QofParam *qof_param;
00785 xmlNodePtr node;
00786 gchar qsf_guid[GUID_ENCODING_LENGTH + 1];
00787
00788 params = (QsfParam *) user_data;
00789 if (!ent || !params)
00790 return;
00791 qof_param = params->qof_param;
00792 guid_to_string_buff (qof_entity_get_guid (ent), qsf_guid);
00793 node = xmlAddChild (params->output_node, xmlNewNode (params->qsf_ns,
00794 BAD_CAST qof_param->param_type));
00795 xmlNodeAddContent (node, BAD_CAST qsf_guid);
00796 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE,
00797 BAD_CAST qof_param->param_name);
00798 }
00799
00800
00801
00802 static gint
00803 qof_reference_list_cb (gconstpointer a, gconstpointer b)
00804 {
00805 const QofEntityReference *aa;
00806 const QofEntityReference *bb;
00807
00808 aa = (QofEntityReference *) a;
00809 bb = (QofEntityReference *) b;
00810 if (aa == NULL)
00811 return 1;
00812 g_return_val_if_fail ((bb != NULL), 1);
00813 g_return_val_if_fail ((aa->type != NULL), 1);
00814 if ((0 == guid_compare (bb->ent_guid, aa->ent_guid))
00815 && (0 == safe_strcmp (bb->type, aa->type))
00816 && (0 == safe_strcmp (bb->param->param_name,
00817 aa->param->param_name)))
00818 return 0;
00819 return 1;
00820 }
00821
00822 static QofEntityReference *
00823 qof_reference_lookup (GList * referenceList, QofEntityReference * find)
00824 {
00825 GList *single_ref;
00826 QofEntityReference *ent_ref;
00827
00828 if (referenceList == NULL)
00829 return NULL;
00830 g_return_val_if_fail (find != NULL, NULL);
00831 single_ref = NULL;
00832 ent_ref = NULL;
00833 single_ref =
00834 g_list_find_custom (referenceList, find, qof_reference_list_cb);
00835 if (single_ref == NULL)
00836 return ent_ref;
00837 ent_ref = (QofEntityReference *) single_ref->data;
00838 g_list_free (single_ref);
00839 return ent_ref;
00840 }
00841
00842 static void
00843 reference_list_lookup (gpointer data, gpointer user_data)
00844 {
00845 QofEntity *ent;
00846 QofParam *ref_param;
00847 QofEntityReference *reference, *starter;
00848 QsfParam *params;
00849 const GUID *guid;
00850 xmlNodePtr node, object_node;
00851 xmlNsPtr ns;
00852 GList *copy_list;
00853 gchar qsf_guid[GUID_ENCODING_LENGTH + 1], *ref_name;
00854
00855 params = (QsfParam *) user_data;
00856 ref_param = (QofParam *) data;
00857 object_node = params->output_node;
00858 ent = params->qsf_ent;
00859 ns = params->qsf_ns;
00860 starter = g_new0 (QofEntityReference, 1);
00861 starter->ent_guid = qof_entity_get_guid (ent);
00862 starter->type = g_strdup (ent->e_type);
00863 starter->param = ref_param;
00864 starter->ref_guid = NULL;
00865 copy_list = g_list_copy (params->referenceList);
00866 reference = qof_reference_lookup (copy_list, starter);
00867 g_free (starter);
00868 if (reference != NULL)
00869 {
00870 if ((ref_param->param_getfcn == NULL)
00871 || (ref_param->param_setfcn == NULL))
00872 return;
00873 ref_name = g_strdup (reference->param->param_name);
00874 node =
00875 xmlAddChild (object_node,
00876 xmlNewNode (ns, BAD_CAST QOF_TYPE_GUID));
00877 guid_to_string_buff (reference->ref_guid, qsf_guid);
00878 xmlNodeAddContent (node, BAD_CAST qsf_guid);
00879 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST ref_name);
00880 g_free (ref_name);
00881 }
00882 else
00883 {
00884 ent = (QofEntity *) ref_param->param_getfcn (ent, ref_param);
00885 if (!ent)
00886 return;
00887 if ((0 == safe_strcmp (ref_param->param_type, QOF_TYPE_COLLECT)) ||
00888 (0 == safe_strcmp (ref_param->param_type, QOF_TYPE_CHOICE)))
00889 return;
00890 node =
00891 xmlAddChild (object_node,
00892 xmlNewNode (ns, BAD_CAST QOF_TYPE_GUID));
00893 guid = qof_entity_get_guid (ent);
00894 guid_to_string_buff (guid, qsf_guid);
00895 xmlNodeAddContent (node, BAD_CAST qsf_guid);
00896 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE,
00897 BAD_CAST ref_param->param_name);
00898 }
00899 }
00900
00901
00902
00903
00904
00905 static void
00906 qsf_entity_foreach (QofEntity * ent, gpointer data)
00907 {
00908 QsfParam *params;
00909 GSList *param_list, *supported;
00910 GList *ref;
00911 xmlNodePtr node, object_node;
00912 xmlNsPtr ns;
00913 gchar *string_buffer;
00914 QofParam *qof_param;
00915 QofEntity *choice_ent;
00916 KvpFrame *qsf_kvp;
00917 QofCollection *qsf_coll;
00918 gint param_count;
00919 gboolean own_guid;
00920 const GUID *cm_guid;
00921 gchar cm_sa[GUID_ENCODING_LENGTH + 1];
00922
00923 g_return_if_fail (data != NULL);
00924 params = (QsfParam *) data;
00925 param_count = ++params->count;
00926 ns = params->qsf_ns;
00927 qsf_kvp = NULL;
00928 own_guid = FALSE;
00929 choice_ent = NULL;
00930 object_node = xmlNewChild (params->book_node, params->qsf_ns,
00931 BAD_CAST QSF_OBJECT_TAG, NULL);
00932 xmlNewProp (object_node, BAD_CAST QSF_OBJECT_TYPE,
00933 BAD_CAST ent->e_type);
00934 string_buffer = g_strdup_printf ("%i", param_count);
00935 xmlNewProp (object_node, BAD_CAST QSF_OBJECT_COUNT,
00936 BAD_CAST string_buffer);
00937 g_free (string_buffer);
00938 param_list = g_slist_copy (params->qsf_sequence);
00939 while (param_list != NULL)
00940 {
00941 qof_param = (QofParam *) param_list->data;
00942 g_return_if_fail (qof_param != NULL);
00943 if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_GUID))
00944 {
00945 if (!own_guid)
00946 {
00947 cm_guid = qof_entity_get_guid (ent);
00948 node = xmlAddChild (object_node, xmlNewNode (ns, BAD_CAST
00949 QOF_TYPE_GUID));
00950 guid_to_string_buff (cm_guid, cm_sa);
00951 string_buffer = g_strdup (cm_sa);
00952 xmlNodeAddContent (node, BAD_CAST string_buffer);
00953 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
00954 QOF_PARAM_GUID);
00955 g_free (string_buffer);
00956 own_guid = TRUE;
00957 }
00958 params->qsf_ent = ent;
00959 params->output_node = object_node;
00960 ref = qof_class_get_referenceList (ent->e_type);
00961 if (ref != NULL)
00962 g_list_foreach (ref, reference_list_lookup, params);
00963 }
00964 if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_COLLECT))
00965 {
00966 qsf_coll = qof_param->param_getfcn (ent, qof_param);
00967 if (qsf_coll)
00968 {
00969 params->qof_param = qof_param;
00970 params->output_node = object_node;
00971 if (qof_collection_count (qsf_coll) > 0)
00972 qof_collection_foreach (qsf_coll, qsf_from_coll_cb,
00973 params);
00974 }
00975 param_list = g_slist_next (param_list);
00976 continue;
00977 }
00978 if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_CHOICE))
00979 {
00981 choice_ent =
00982 (QofEntity *) qof_param->param_getfcn (ent, qof_param);
00983 if (!choice_ent)
00984 {
00985 param_list = g_slist_next (param_list);
00986 continue;
00987 }
00988 node = xmlAddChild (object_node, xmlNewNode (ns, BAD_CAST
00989 qof_param->param_type));
00990 cm_guid = qof_entity_get_guid (choice_ent);
00991 guid_to_string_buff (cm_guid, cm_sa);
00992 string_buffer = g_strdup (cm_sa);
00993 xmlNodeAddContent (node, BAD_CAST string_buffer);
00994 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
00995 qof_param->param_name);
00996 xmlNewProp (node, BAD_CAST "name",
00997 BAD_CAST choice_ent->e_type);
00998 g_free (string_buffer);
00999 param_list = g_slist_next (param_list);
01000 continue;
01001 }
01002 if (0 == safe_strcmp (qof_param->param_type, QOF_TYPE_KVP))
01003 {
01004 qsf_kvp =
01005 (KvpFrame *) qof_param->param_getfcn (ent, qof_param);
01006 if (kvp_frame_is_empty (qsf_kvp))
01007 return;
01008 params->qof_param = qof_param;
01009 params->output_node = object_node;
01010 kvp_frame_for_each_slot (qsf_kvp, qsf_from_kvp_helper, params);
01011 }
01012 if ((qof_param->param_setfcn != NULL)
01013 && (qof_param->param_getfcn != NULL))
01014 {
01015 for (supported = g_slist_copy (params->supported_types);
01016 supported != NULL; supported = g_slist_next (supported))
01017 {
01018 if (0 == safe_strcmp ((const gchar *) supported->data,
01019 (const gchar *) qof_param->param_type))
01020 {
01021 node = xmlAddChild (object_node,
01022 xmlNewNode (ns, BAD_CAST qof_param->param_type));
01023 string_buffer =
01024 g_strdup (qof_util_param_to_string
01025 (ent, qof_param));
01026 xmlNodeAddContent (node, BAD_CAST string_buffer);
01027 xmlNewProp (node, BAD_CAST QSF_OBJECT_TYPE, BAD_CAST
01028 qof_param->param_name);
01029 g_free (string_buffer);
01030 }
01031 }
01032 }
01033 param_list = g_slist_next (param_list);
01034 }
01035 }
01036
01037 static void
01038 qsf_foreach_obj_type (QofObject * qsf_obj, gpointer data)
01039 {
01040 QsfParam *params;
01041 QofBook *book;
01042 GSList *support;
01043
01044 g_return_if_fail (data != NULL);
01045 params = (QsfParam *) data;
01046
01047 if ((qsf_obj->create == NULL) || (qsf_obj->foreach == NULL))
01048 {
01049 PINFO (" qsf_obj QOF support failed %s", qsf_obj->e_type);
01050 return;
01051 }
01052 params->qof_obj_type = qsf_obj->e_type;
01053 params->qsf_sequence = NULL;
01054 book = params->book;
01055 support = g_slist_copy (params->supported_types);
01056 g_slist_foreach (support, qsf_supported_parameters, params);
01057 qof_object_foreach (qsf_obj->e_type, book, qsf_entity_foreach, params);
01058 }
01059
01060
01061
01062
01063
01064 static xmlDocPtr
01065 qofbook_to_qsf (QofBook * book, QsfParam * params)
01066 {
01067 xmlNodePtr top_node, node;
01068 xmlDocPtr doc;
01069 gchar buffer[GUID_ENCODING_LENGTH + 1];
01070 const GUID *book_guid;
01071
01072 g_return_val_if_fail (book != NULL, NULL);
01073 params->book = book;
01074 params->referenceList =
01075 g_list_copy ((GList *) qof_book_get_data (book,
01076 ENTITYREFERENCE));
01077 doc = xmlNewDoc (BAD_CAST QSF_XML_VERSION);
01078 top_node = xmlNewNode (NULL, BAD_CAST QSF_ROOT_TAG);
01079 xmlDocSetRootElement (doc, top_node);
01080 xmlSetNs (top_node, xmlNewNs (top_node, BAD_CAST QSF_DEFAULT_NS,
01081 NULL));
01082 params->qsf_ns = top_node->ns;
01083 node =
01084 xmlNewChild (top_node, params->qsf_ns, BAD_CAST QSF_BOOK_TAG,
01085 NULL);
01086 params->book_node = node;
01087 xmlNewProp (node, BAD_CAST QSF_BOOK_COUNT, BAD_CAST "1");
01088 book_guid = qof_entity_get_guid ((QofEntity*)book);
01089 guid_to_string_buff (book_guid, buffer);
01090 xmlNewChild (params->book_node, params->qsf_ns,
01091 BAD_CAST QSF_BOOK_GUID, BAD_CAST buffer);
01092 params->output_doc = doc;
01093 params->book_node = node;
01094 qof_object_foreach_type (qsf_foreach_obj_type, params);
01095 return params->output_doc;
01096 }
01097
01098 static void
01099 write_qsf_from_book (const gchar *path, QofBook * book,
01100 QsfParam * params)
01101 {
01102 xmlDocPtr qsf_doc;
01103 gint write_result;
01104 QofBackend *be;
01105
01106 be = qof_book_get_backend (book);
01107 qsf_doc = qofbook_to_qsf (book, params);
01108 write_result = 0;
01109 PINFO (" use_gz_level=%" G_GINT64_FORMAT " encoding=%s",
01110 params->use_gz_level, params->encoding);
01111 if ((params->use_gz_level > 0) && (params->use_gz_level <= 9))
01112 xmlSetDocCompressMode (qsf_doc, params->use_gz_level);
01113 g_return_if_fail (qsf_is_valid
01114 (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
01115 write_result =
01116 xmlSaveFormatFileEnc (path, qsf_doc, params->encoding, 1);
01117 if (write_result < 0)
01118 {
01119 qof_error_set_be (be, qof_error_register
01120 (_("Could not write to '%s'. Check that you have "
01121 "permission to write to this file and that there is "
01122 "sufficient space to create it."), TRUE));
01123 return;
01124 }
01125 qof_object_mark_clean (book);
01126 }
01127
01128 static void
01129 write_qsf_to_stdout (QofBook * book, QsfParam * params)
01130 {
01131 xmlDocPtr qsf_doc;
01132
01133 qsf_doc = qofbook_to_qsf (book, params);
01134 g_return_if_fail (qsf_is_valid
01135 (QSF_SCHEMA_DIR, QSF_OBJECT_SCHEMA, qsf_doc) == TRUE);
01136 PINFO (" use_gz_level=%" G_GINT64_FORMAT " encoding=%s",
01137 params->use_gz_level, params->encoding);
01138 xmlSaveFormatFileEnc ("-", qsf_doc, params->encoding, 1);
01139 fprintf (stdout, "\n");
01140 qof_object_mark_clean (book);
01141 }
01142
01143 static void
01144 qsf_write_file (QofBackend * be, QofBook * book)
01145 {
01146 QSFBackend *qsf_be;
01147 QsfParam *params;
01148 gchar *path;
01149
01150 qsf_be = (QSFBackend *) be;
01151 params = qsf_be->params;
01152
01153 if (!qsf_be->fullpath || (*qsf_be->fullpath == '\0'))
01154 {
01155 write_qsf_to_stdout (book, params);
01156 return;
01157 }
01158 path = strdup (qsf_be->fullpath);
01159 write_qsf_from_book (path, book, params);
01160 g_free (path);
01161 }
01162
01163 KvpValue *
01164 string_to_kvp_value (const gchar * content, KvpValueType type)
01165 {
01166 gchar *tail;
01167 gint64 cm_i64;
01168 gdouble cm_double;
01169 QofNumeric cm_numeric;
01170 GUID *cm_guid;
01171
01172 switch (type)
01173 {
01174 case KVP_TYPE_GINT64:
01175 {
01176 errno = 0;
01177 cm_i64 = strtoll (content, &tail, 0);
01178 if (errno == 0)
01179 {
01180 return kvp_value_new_gint64 (cm_i64);
01181 }
01182 break;
01183 }
01184 case KVP_TYPE_DOUBLE:
01185 {
01186 errno = 0;
01187 cm_double = strtod (content, &tail);
01188 if (errno == 0)
01189 return kvp_value_new_double (cm_double);
01190 break;
01191 }
01192 case KVP_TYPE_NUMERIC:
01193 {
01194 qof_numeric_from_string (content, &cm_numeric);
01195 return kvp_value_new_numeric (cm_numeric);
01196 break;
01197 }
01198 case KVP_TYPE_STRING:
01199 {
01200 return kvp_value_new_string (content);
01201 break;
01202 }
01203 case KVP_TYPE_GUID:
01204 {
01205 cm_guid = g_new0 (GUID, 1);
01206 if (TRUE == string_to_guid (content, cm_guid))
01207 return kvp_value_new_guid (cm_guid);
01208 break;
01209 }
01210 case KVP_TYPE_TIME :
01211 {
01212 QofDate *qd;
01213 QofTime *qt;
01214 KvpValue *retval;
01215
01216 qd = qof_date_parse (content, QOF_DATE_FORMAT_UTC);
01217 if(qd)
01218 {
01219 qt = qof_date_to_qtime (qd);
01220 retval = kvp_value_new_time (qt);
01221 qof_date_free (qd);
01222 qof_time_free (qt);
01223 return retval;
01224 }
01225 else
01226 PERR (" failed to parse date");
01227 }
01228 case KVP_TYPE_BOOLEAN :
01229 {
01230 gboolean val;
01231 val = qof_util_bool_to_int (content);
01232 return kvp_value_new_boolean (val);
01233 }
01234 case KVP_TYPE_BINARY:
01235
01236
01237 break;
01238 case KVP_TYPE_GLIST:
01239
01240 break;
01241 case KVP_TYPE_FRAME:
01242
01243 break;
01244 }
01245 return NULL;
01246 }
01247
01248
01249
01250
01251 void
01252 qsf_object_commitCB (gpointer key, gpointer value, gpointer data)
01253 {
01254 QsfParam *params;
01255 QsfObject *object_set;
01256 xmlNodePtr node;
01257 QofEntityReference *reference;
01258 QofEntity *qsf_ent;
01259 QofBook *targetBook;
01260 const gchar *qof_type, *parameter_name;
01261 QofIdType obj_type, reference_type;
01262 gchar *tail;
01263
01264 QofNumeric cm_numeric;
01265 gdouble cm_double;
01266 gboolean cm_boolean;
01267 gint32 cm_i32;
01268 gint64 cm_i64;
01269 gchar cm_char, (*char_getter) (xmlNodePtr);
01270 GUID *cm_guid;
01271 KvpFrame *cm_kvp;
01272 KvpValue *cm_value;
01273 KvpValueType cm_type;
01274 QofSetterFunc cm_setter;
01275 const QofParam *cm_param;
01276 void (*string_setter) (QofEntity *, const gchar *);
01277 void (*time_setter) (QofEntity *, QofTime *);
01278 void (*numeric_setter) (QofEntity *, QofNumeric);
01279 void (*double_setter) (QofEntity *, gdouble);
01280 void (*boolean_setter) (QofEntity *, gboolean);
01281 void (*i32_setter) (QofEntity *, gint32);
01282 void (*i64_setter) (QofEntity *, gint64);
01283 void (*char_setter) (QofEntity *, gchar);
01284
01285 g_return_if_fail (data && value && key);
01286 params = (QsfParam *) data;
01287 node = (xmlNodePtr) value;
01288 parameter_name = (const gchar *) key;
01289 qof_type = (gchar *) node->name;
01290 qsf_ent = params->qsf_ent;
01291 targetBook = params->book;
01292 obj_type =
01293 (gchar *) xmlGetProp (node->parent, BAD_CAST QSF_OBJECT_TYPE);
01294 if (0 == safe_strcasecmp (obj_type, parameter_name))
01295 {
01296 return;
01297 }
01298 cm_setter = qof_class_get_parameter_setter (obj_type, parameter_name);
01299 cm_param = qof_class_get_parameter (obj_type, parameter_name);
01300 object_set = params->object_set;
01301 if (safe_strcmp (qof_type, QOF_TYPE_STRING) == 0)
01302 {
01303 string_setter = (void (*)(QofEntity *, const gchar *)) cm_setter;
01304 if (string_setter != NULL)
01305 {
01306 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
01307 string_setter (qsf_ent, (gchar *) xmlNodeGetContent (node));
01308 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
01309 }
01310 }
01311 if (safe_strcmp (qof_type, QOF_TYPE_TIME) == 0)
01312 {
01313 time_setter = (void (*)(QofEntity *, QofTime*)) cm_setter;
01314 if (time_setter != NULL)
01315 {
01316 QofDate *qd;
01317 QofTime *qt;
01318
01319 qd = qof_date_parse (
01320 (const gchar*) xmlNodeGetContent (node),
01321 QOF_DATE_FORMAT_UTC);
01322 if(qd)
01323 {
01324 qt = qof_date_to_qtime (qd);
01325 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
01326 time_setter (qsf_ent, qt);
01327 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
01328 qof_date_free (qd);
01329 }
01330 else
01331 PERR (" failed to parse date string");
01332 }
01333 }
01334 if ((safe_strcmp (qof_type, QOF_TYPE_NUMERIC) == 0) ||
01335 (safe_strcmp (qof_type, QOF_TYPE_DEBCRED) == 0))
01336 {
01337 gchar *tmp;
01338 numeric_setter = (void (*)(QofEntity *, QofNumeric)) cm_setter;
01339 tmp = (char *) xmlNodeGetContent (node);
01340 qof_numeric_from_string (tmp, &cm_numeric);
01341 g_free (tmp);
01342 if (numeric_setter != NULL)
01343 {
01344 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
01345 numeric_setter (qsf_ent, cm_numeric);
01346 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
01347 }
01348 }
01349 if (safe_strcmp (qof_type, QOF_TYPE_GUID) == 0)
01350 {
01351 cm_guid = g_new0 (GUID, 1);
01352 if (TRUE !=
01353 string_to_guid ((gchar *) xmlNodeGetContent (node), cm_guid))
01354 {
01355 qof_error_set_be (params->be, qof_error_register(
01356 _("The selected QSF object file '%s' contains one or "
01357 "more invalid GUIDs. The file cannot be processed - "
01358 "please check the source of the file and try again."),
01359 TRUE));
01360 PINFO (" string to guid conversion failed for %s:%s:%s",
01361 xmlNodeGetContent (node), obj_type, qof_type);
01362 return;
01363 }
01364 reference_type =
01365 (gchar *) xmlGetProp (node, BAD_CAST QSF_OBJECT_TYPE);
01366 if (0 == safe_strcmp (QOF_PARAM_GUID, reference_type))
01367 {
01368 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
01369 qof_entity_set_guid (qsf_ent, cm_guid);
01370 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
01371 }
01372 else
01373 {
01374 reference = qof_entity_get_reference_from (qsf_ent, cm_param);
01375 if (reference)
01376 {
01377 params->referenceList =
01378 g_list_append (params->referenceList, reference);
01379 }
01380 }
01381 }
01382 if (safe_strcmp (qof_type, QOF_TYPE_INT32) == 0)
01383 {
01384 errno = 0;
01385 cm_i32 =
01386 (gint32) strtol ((char *) xmlNodeGetContent (node), &tail, 0);
01387 if (errno == 0)
01388 {
01389 i32_setter = (void (*)(QofEntity *, gint32)) cm_setter;
01390 if (i32_setter != NULL)
01391 {
01392 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
01393 i32_setter (qsf_ent, cm_i32);
01394 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
01395 }
01396 }
01397 else
01398 qof_error_set_be (params->be, params->err_overflow);
01399 }
01400 if (safe_strcmp (qof_type, QOF_TYPE_INT64) == 0)
01401 {
01402 errno = 0;
01403 cm_i64 = strtoll ((gchar *) xmlNodeGetContent (node), &tail, 0);
01404 if (errno == 0)
01405 {
01406 i64_setter = (void (*)(QofEntity *, gint64)) cm_setter;
01407 if (i64_setter != NULL)
01408 {
01409 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
01410 i64_setter (qsf_ent, cm_i64);
01411 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
01412 }
01413 }
01414 else
01415 qof_error_set_be (params->be, params->err_overflow);
01416 }
01417 if (safe_strcmp (qof_type, QOF_TYPE_DOUBLE) == 0)
01418 {
01419 errno = 0;
01420 cm_double = strtod ((gchar *) xmlNodeGetContent (node), &tail);
01421 if (errno == 0)
01422 {
01423 double_setter = (void (*)(QofEntity *, gdouble)) cm_setter;
01424 if (double_setter != NULL)
01425 {
01426 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
01427 double_setter (qsf_ent, cm_double);
01428 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
01429 }
01430 }
01431 }
01432 if (safe_strcmp (qof_type, QOF_TYPE_BOOLEAN) == 0)
01433 {
01434 if (0 == safe_strcasecmp ((gchar *) xmlNodeGetContent (node),
01435 QSF_XML_BOOLEAN_TEST))
01436 cm_boolean = TRUE;
01437 else
01438 cm_boolean = FALSE;
01439 boolean_setter = (void (*)(QofEntity *, gboolean)) cm_setter;
01440 if (boolean_setter != NULL)
01441 {
01442 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
01443 boolean_setter (qsf_ent, cm_boolean);
01444 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
01445 }
01446 }
01447 if (safe_strcmp (qof_type, QOF_TYPE_KVP) == 0)
01448 {
01449 cm_type =
01450 qsf_to_kvp_helper ((gchar *)
01451 xmlGetProp (node, BAD_CAST QSF_OBJECT_VALUE));
01452 if (!cm_type)
01453 return;
01454 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
01455 cm_value =
01456 string_to_kvp_value ((gchar *) xmlNodeGetContent (node),
01457 cm_type);
01458 cm_kvp = (KvpFrame *) cm_param->param_getfcn (qsf_ent, cm_param);
01459 cm_kvp = kvp_frame_set_value (cm_kvp, (gchar *) xmlGetProp (node,
01460 BAD_CAST QSF_OBJECT_KVP), cm_value);
01461 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
01462 g_free (cm_value);
01463 }
01464 if (safe_strcmp (qof_type, QOF_TYPE_COLLECT) == 0)
01465 {
01466 QofCollection *qsf_coll;
01467 QofIdType type;
01468 QofEntityReference *reference;
01469 QofParam *copy_param;
01470
01471 qsf_coll = cm_param->param_getfcn (qsf_ent, cm_param);
01472 type = qof_collection_get_type (qsf_coll);
01473 cm_guid = g_new0 (GUID, 1);
01474 if (TRUE !=
01475 string_to_guid ((gchar *) xmlNodeGetContent (node), cm_guid))
01476 {
01477 qof_error_set_be (params->be, (qof_error_register(
01478 _("The selected QSF object file '%s' contains one or "
01479 "more invalid 'collect' values. The file cannot be processed - "
01480 "please check the source of the file and try again."),
01481 TRUE)));
01482 PINFO (" string to guid collect failed for %s",
01483 xmlNodeGetContent (node));
01484 return;
01485 }
01486
01487
01488
01489
01490 reference = g_new0 (QofEntityReference, 1);
01491 reference->type = g_strdup (qsf_ent->e_type);
01492 reference->ref_guid = cm_guid;
01493 reference->ent_guid = &qsf_ent->guid;
01494 copy_param = g_new0 (QofParam, 1);
01495 copy_param->param_name = g_strdup (cm_param->param_name);
01496 copy_param->param_type = g_strdup (cm_param->param_type);
01497 reference->param = copy_param;
01498 params->referenceList =
01499 g_list_append (params->referenceList, reference);
01500 }
01501 if (safe_strcmp (qof_type, QOF_TYPE_CHAR) == 0)
01502 {
01503 char_getter = (gchar (*)(xmlNodePtr)) xmlNodeGetContent;
01504 cm_char = char_getter (node);
01505 char_setter = (void (*)(QofEntity *, gchar)) cm_setter;
01506 if (char_setter != NULL)
01507 {
01508 qof_util_param_edit ((QofInstance *) qsf_ent, cm_param);
01509 char_setter (qsf_ent, cm_char);
01510 qof_util_param_commit ((QofInstance *) qsf_ent, cm_param);
01511 }
01512 }
01513 }
01514
01515 static QofBackend *
01516 qsf_backend_new (void)
01517 {
01518 QSFBackend *qsf_be;
01519 QofBackend *be;
01520
01521 qsf_be = g_new0 (QSFBackend, 1);
01522 be = (QofBackend *) qsf_be;
01523 qof_backend_init (be);
01524 qsf_be->params = g_new0 (QsfParam, 1);
01525 qsf_be->params->be = be;
01526 qsf_param_init (qsf_be->params);
01527 qsf_be->be.session_begin = qsf_session_begin;
01528
01529 be->session_end = qsf_session_end;
01530 be->destroy_backend = qsf_destroy_backend;
01531 be->load = qsf_file_type;
01532 be->save_may_clobber_data = NULL;
01533
01534 be->begin = NULL;
01535 be->commit = NULL;
01536 be->rollback = NULL;
01537
01538 be->compile_query = NULL;
01539 be->free_query = NULL;
01540 be->run_query = NULL;
01541 be->counter = NULL;
01542
01543 be->events_pending = NULL;
01544 be->process_events = NULL;
01545
01546 be->sync = qsf_write_file;
01547
01548 be->load_config = qsf_load_config;
01549 be->get_config = qsf_get_config;
01550
01551 qsf_be->fullpath = NULL;
01552 return be;
01553 }
01554
01555
01556
01557
01558 static void
01559 qsf_provider_free (QofBackendProvider * prov)
01560 {
01561 prov->provider_name = NULL;
01562 prov->access_method = NULL;
01563 g_free (prov);
01564 }
01565
01566 void
01567 qsf_provider_init (void)
01568 {
01569 QofBackendProvider *prov;
01570
01571 bindtextdomain (PACKAGE, LOCALE_DIR);
01572 prov = g_new0 (QofBackendProvider, 1);
01573 prov->provider_name = "QSF Backend Version 0.4";
01574 prov->access_method = "file";
01575 prov->partial_book_supported = TRUE;
01576 prov->backend_new = qsf_backend_new;
01577 prov->check_data_type = qsf_determine_file_type;
01578 prov->provider_free = qsf_provider_free;
01579 qof_backend_register_provider (prov);
01580 }