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