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