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