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