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