00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00034 #include "config.h"
00035
00036 #include <stdlib.h>
00037 #include <string.h>
00038 #include <sys/types.h>
00039 #include <sys/stat.h>
00040 #include <unistd.h>
00041 #include <glib.h>
00042 #include <libintl.h>
00043 #include "qof.h"
00044 #include "qoferror-p.h"
00045 #include "qofbackend-p.h"
00046 #include "qofbook-p.h"
00047 #include "qofsession-p.h"
00048 #include "qofobject-p.h"
00049
00050 #define _(String) dgettext (GETTEXT_PACKAGE, String)
00051
00052 static GHookList *session_closed_hooks = NULL;
00053 static QofLogModule log_module = QOF_MOD_SESSION;
00054 static GSList *provider_list = NULL;
00055
00056
00057
00058 void
00059 qof_backend_register_provider (QofBackendProvider * prov)
00060 {
00061 provider_list = g_slist_prepend (provider_list, prov);
00062 }
00063
00064
00065
00066
00067
00068 void
00069 qof_session_add_close_hook (GFunc fn, gpointer data)
00070 {
00071 GHook *hook;
00072
00073 if (session_closed_hooks == NULL)
00074 {
00075 session_closed_hooks = malloc (sizeof (GHookList));
00076 g_hook_list_init (session_closed_hooks, sizeof (GHook));
00077 }
00078
00079 hook = g_hook_alloc (session_closed_hooks);
00080 if (!hook)
00081 return;
00082
00083 hook->func = (GHookFunc) fn;
00084 hook->data = data;
00085 g_hook_append (session_closed_hooks, hook);
00086 }
00087
00088 void
00089 qof_session_call_close_hooks (QofSession * session)
00090 {
00091 GHook *hook;
00092 GFunc fn;
00093
00094 if (session_closed_hooks == NULL)
00095 return;
00096
00097 hook = g_hook_first_valid (session_closed_hooks, FALSE);
00098 while (hook)
00099 {
00100 fn = (GFunc) hook->func;
00101 fn (session, hook->data);
00102 hook = g_hook_next_valid (session_closed_hooks, hook, FALSE);
00103 }
00104 }
00105
00106
00107
00108 static void
00109 qof_session_init (QofSession * session)
00110 {
00111 if (!session)
00112 return;
00113
00114 session->books = g_list_append (NULL, qof_book_new ());
00115 session->book_id = NULL;
00116 session->backend = NULL;
00117 qof_error_init ();
00118 }
00119
00120 QofSession *
00121 qof_session_new (void)
00122 {
00123 QofSession *session = g_new0 (QofSession, 1);
00124 qof_session_init (session);
00125 return session;
00126 }
00127
00128 QofBook *
00129 qof_session_get_book (QofSession * session)
00130 {
00131 GList *node;
00132 if (!session)
00133 return NULL;
00134
00135 for (node = session->books; node; node = node->next)
00136 {
00137 QofBook *book = node->data;
00138 if ('y' == book->book_open)
00139 return book;
00140 }
00141 return NULL;
00142 }
00143
00144 void
00145 qof_session_add_book (QofSession * session, QofBook * addbook)
00146 {
00147 GList *node;
00148 if (!session)
00149 return;
00150
00151 ENTER (" sess=%p book=%p", session, addbook);
00152
00153
00154 for (node = session->books; node; node = node->next)
00155 {
00156 QofBook *book = node->data;
00157 if (addbook == book)
00158 return;
00159 }
00160
00161 if ('y' == addbook->book_open)
00162 {
00163
00164
00165
00166
00167 g_list_free (session->books);
00168 session->books = g_list_append (NULL, addbook);
00169 }
00170 else
00171 {
00172
00173 session->books = g_list_append (session->books, addbook);
00174 }
00175
00176 qof_book_set_backend (addbook, session->backend);
00177 LEAVE (" ");
00178 }
00179
00180 QofBackend *
00181 qof_session_get_backend (QofSession * session)
00182 {
00183 if (!session)
00184 return NULL;
00185 return session->backend;
00186 }
00187
00188 const gchar *
00189 qof_session_get_file_path (QofSession * session)
00190 {
00191 if (!session)
00192 return NULL;
00193 if (!session->backend)
00194 return NULL;
00195 return session->backend->fullpath;
00196 }
00197
00198 const gchar *
00199 qof_session_get_url (QofSession * session)
00200 {
00201 if (!session)
00202 return NULL;
00203 return session->book_id;
00204 }
00205
00206
00207
00208 typedef struct qof_entity_copy_data
00209 {
00210 QofEntity *from;
00211 QofEntity *to;
00212 QofParam *param;
00213 GList *referenceList;
00214 GSList *param_list;
00215 QofSession *new_session;
00216 gboolean error;
00217 } QofEntityCopyData;
00218
00219 static void
00220 qof_book_set_partial (QofBook * book)
00221 {
00222 gboolean partial;
00223
00224 partial =
00225 (gboolean)
00226 GPOINTER_TO_INT (qof_book_get_data (book, PARTIAL_QOFBOOK));
00227 if (!partial)
00228 {
00229 qof_book_set_data (book, PARTIAL_QOFBOOK, GINT_TO_POINTER (TRUE));
00230 }
00231 }
00232
00233 void
00234 qof_session_update_reference_list (QofSession * session,
00235 QofEntityReference * reference)
00236 {
00237 QofBook *book;
00238 GList *book_ref_list;
00239
00240 book = qof_session_get_book (session);
00241 book_ref_list = (GList *) qof_book_get_data (book, ENTITYREFERENCE);
00242 book_ref_list = g_list_append (book_ref_list, reference);
00243 qof_book_set_data (book, ENTITYREFERENCE, book_ref_list);
00244 qof_book_set_partial (book);
00245 }
00246
00247 static void
00248 qof_entity_param_cb (QofParam * param, gpointer data)
00249 {
00250 QofEntityCopyData *qecd;
00251
00252 g_return_if_fail (data != NULL);
00253 qecd = (QofEntityCopyData *) data;
00254 g_return_if_fail (param != NULL);
00255
00256 if (0 == safe_strcmp (param->param_type, QOF_TYPE_KVP))
00257 {
00258 qecd->param_list = g_slist_prepend (qecd->param_list, param);
00259 return;
00260 }
00261 if ((param->param_getfcn != NULL) && (param->param_setfcn != NULL))
00262 {
00263 qecd->param_list = g_slist_prepend (qecd->param_list, param);
00264 }
00265 }
00266
00267 static void
00268 col_ref_cb (QofEntity * ref_ent, gpointer user_data)
00269 {
00270 QofEntityReference *ref;
00271 QofEntityCopyData *qecd;
00272 QofEntity *ent;
00273 const GUID *cm_guid;
00274 gchar cm_sa[GUID_ENCODING_LENGTH + 1];
00275 gchar *cm_string;
00276
00277 qecd = (QofEntityCopyData *) user_data;
00278 ent = qecd->from;
00279 ref = g_new0 (QofEntityReference, 1);
00280 ref->type = ent->e_type;
00281 ref->ref_guid = g_new (GUID, 1);
00282 ref->ent_guid = &ent->guid;
00283 ref->param = qof_class_get_parameter (ent->e_type,
00284 qecd->param->param_name);
00285 cm_guid = qof_entity_get_guid (ref_ent);
00286 guid_to_string_buff (cm_guid, cm_sa);
00287 cm_string = g_strdup (cm_sa);
00288 if (TRUE == string_to_guid (cm_string, ref->ref_guid))
00289 {
00290 g_free (cm_string);
00291 qof_session_update_reference_list (qecd->new_session, ref);
00292 }
00293 }
00294
00295 static void
00296 qof_entity_foreach_copy (gpointer data, gpointer user_data)
00297 {
00298 QofEntity *importEnt, *targetEnt ;
00299 QofEntityCopyData *context;
00300 QofEntityReference *reference;
00301 gboolean registered_type;
00302
00303 QofParam *cm_param;
00304 gchar *cm_string, *cm_char;
00305 const GUID *cm_guid;
00306 KvpFrame *cm_kvp;
00307 QofCollection *cm_col;
00308
00309 QofNumeric cm_numeric, (*numeric_getter) (QofEntity *, QofParam *);
00310 gdouble cm_double, (*double_getter) (QofEntity *, QofParam *);
00311 gboolean cm_boolean, (*boolean_getter) (QofEntity *, QofParam *);
00312 gint32 cm_i32, (*int32_getter) (QofEntity *, QofParam *);
00313 gint64 cm_i64, (*int64_getter) (QofEntity *, QofParam *);
00314
00315 void (*string_setter) (QofEntity *, const gchar *);
00316 void (*numeric_setter) (QofEntity *, QofNumeric);
00317 void (*guid_setter) (QofEntity *, const GUID *);
00318 void (*double_setter) (QofEntity *, gdouble);
00319 void (*boolean_setter) (QofEntity *, gboolean);
00320 void (*i32_setter) (QofEntity *, gint32);
00321 void (*i64_setter) (QofEntity *, gint64);
00322 void (*char_setter) (QofEntity *, gchar *);
00323 void (*kvp_frame_setter) (QofEntity *, KvpFrame *);
00324
00325 g_return_if_fail (user_data != NULL);
00326 context = (QofEntityCopyData *) user_data;
00327 importEnt = context->from;
00328 targetEnt = context->to;
00329 registered_type = FALSE;
00330 cm_param = (QofParam *) data;
00331 g_return_if_fail (cm_param != NULL);
00332 context->param = cm_param;
00333 if (safe_strcmp (cm_param->param_type, QOF_TYPE_STRING) == 0)
00334 {
00335 cm_string = (gchar *) cm_param->param_getfcn (importEnt, cm_param);
00336 if (cm_string)
00337 {
00338 string_setter =
00339 (void (*)(QofEntity *,
00340 const char *)) cm_param->param_setfcn;
00341 if (string_setter != NULL)
00342 {
00343 qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
00344 string_setter (targetEnt, cm_string);
00345 qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
00346 }
00347 }
00348 registered_type = TRUE;
00349 }
00350 if (safe_strcmp (cm_param->param_type, QOF_TYPE_TIME) == 0)
00351 {
00352 QofTime *qt;
00353 void (*time_setter) (QofEntity *, QofTime *);
00354
00355 qt = cm_param->param_getfcn (importEnt, cm_param);
00356 time_setter =
00357 (void (*)(QofEntity *, QofTime*))cm_param->param_setfcn;
00358 if (time_setter != NULL)
00359 {
00360 qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
00361 time_setter (targetEnt, qt);
00362 qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
00363 }
00364 registered_type = TRUE;
00365 }
00366 if ((safe_strcmp (cm_param->param_type, QOF_TYPE_NUMERIC) == 0) ||
00367 (safe_strcmp (cm_param->param_type, QOF_TYPE_DEBCRED) == 0))
00368 {
00369 numeric_getter =
00370 (QofNumeric (*)(QofEntity *,
00371 QofParam *)) cm_param->param_getfcn;
00372 cm_numeric = numeric_getter (importEnt, cm_param);
00373 numeric_setter =
00374 (void (*)(QofEntity *, QofNumeric)) cm_param->param_setfcn;
00375 if (numeric_setter != NULL)
00376 {
00377 qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
00378 numeric_setter (targetEnt, cm_numeric);
00379 qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
00380 }
00381 registered_type = TRUE;
00382 }
00383 if (safe_strcmp (cm_param->param_type, QOF_TYPE_GUID) == 0)
00384 {
00385 cm_guid =
00386 (const GUID *) cm_param->param_getfcn (importEnt, cm_param);
00387 guid_setter =
00388 (void (*)(QofEntity *, const GUID *)) cm_param->param_setfcn;
00389 if (guid_setter != NULL)
00390 {
00391 qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
00392 guid_setter (targetEnt, cm_guid);
00393 qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
00394 }
00395 registered_type = TRUE;
00396 }
00397 if (safe_strcmp (cm_param->param_type, QOF_TYPE_INT32) == 0)
00398 {
00399 int32_getter =
00400 (gint32 (*)(QofEntity *, QofParam *)) cm_param->param_getfcn;
00401 cm_i32 = int32_getter (importEnt, cm_param);
00402 i32_setter =
00403 (void (*)(QofEntity *, gint32)) cm_param->param_setfcn;
00404 if (i32_setter != NULL)
00405 {
00406 qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
00407 i32_setter (targetEnt, cm_i32);
00408 qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
00409 }
00410 registered_type = TRUE;
00411 }
00412 if (safe_strcmp (cm_param->param_type, QOF_TYPE_INT64) == 0)
00413 {
00414 int64_getter =
00415 (gint64 (*)(QofEntity *, QofParam *)) cm_param->param_getfcn;
00416 cm_i64 = int64_getter (importEnt, cm_param);
00417 i64_setter =
00418 (void (*)(QofEntity *, gint64)) cm_param->param_setfcn;
00419 if (i64_setter != NULL)
00420 {
00421 qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
00422 i64_setter (targetEnt, cm_i64);
00423 qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
00424 }
00425 registered_type = TRUE;
00426 }
00427 if (safe_strcmp (cm_param->param_type, QOF_TYPE_DOUBLE) == 0)
00428 {
00429 double_getter =
00430 (gdouble (*)(QofEntity *, QofParam *)) cm_param->param_getfcn;
00431 cm_double = double_getter (importEnt, cm_param);
00432 double_setter =
00433 (void (*)(QofEntity *, gdouble)) cm_param->param_setfcn;
00434 if (double_setter != NULL)
00435 {
00436 qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
00437 double_setter (targetEnt, cm_double);
00438 qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
00439 }
00440 registered_type = TRUE;
00441 }
00442 if (safe_strcmp (cm_param->param_type, QOF_TYPE_BOOLEAN) == 0)
00443 {
00444 boolean_getter =
00445 (gboolean (*)(QofEntity *, QofParam *)) cm_param->param_getfcn;
00446 cm_boolean = boolean_getter (importEnt, cm_param);
00447 boolean_setter =
00448 (void (*)(QofEntity *, gboolean)) cm_param->param_setfcn;
00449 if (boolean_setter != NULL)
00450 {
00451 qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
00452 boolean_setter (targetEnt, cm_boolean);
00453 qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
00454 }
00455 registered_type = TRUE;
00456 }
00457 if (safe_strcmp (cm_param->param_type, QOF_TYPE_KVP) == 0)
00458 {
00459 cm_kvp = (KvpFrame *) cm_param->param_getfcn (importEnt, cm_param);
00460 kvp_frame_setter =
00461 (void (*)(QofEntity *, KvpFrame *)) cm_param->param_setfcn;
00462 if (kvp_frame_setter != NULL)
00463 {
00464 qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
00465 kvp_frame_setter (targetEnt, cm_kvp);
00466 qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
00467 }
00468 else
00469 {
00470 QofInstance *target_inst;
00471
00472 target_inst = (QofInstance *) targetEnt;
00473 kvp_frame_delete (target_inst->kvp_data);
00474 target_inst->kvp_data = kvp_frame_copy (cm_kvp);
00475 }
00476 registered_type = TRUE;
00477 }
00478 if (safe_strcmp (cm_param->param_type, QOF_TYPE_CHAR) == 0)
00479 {
00480 cm_char = (gchar *) cm_param->param_getfcn (importEnt, cm_param);
00481 char_setter =
00482 (void (*)(QofEntity *, char *)) cm_param->param_setfcn;
00483 if (char_setter != NULL)
00484 {
00485 qof_util_param_edit ((QofInstance *) targetEnt, cm_param);
00486 char_setter (targetEnt, cm_char);
00487 qof_util_param_commit ((QofInstance *) targetEnt, cm_param);
00488 }
00489 registered_type = TRUE;
00490 }
00491 if (safe_strcmp (cm_param->param_type, QOF_TYPE_COLLECT) == 0)
00492 {
00493 cm_col =
00494 (QofCollection *) cm_param->param_getfcn (importEnt, cm_param);
00495 if (cm_col)
00496 {
00497
00498 qof_collection_foreach (cm_col, col_ref_cb, context);
00499 }
00500 registered_type = TRUE;
00501 }
00502 if (registered_type == FALSE)
00503 {
00504
00505
00506
00507 reference = qof_entity_get_reference_from (importEnt, cm_param);
00508 if (reference)
00509 {
00510 qof_session_update_reference_list (context->new_session,
00511 reference);
00512 }
00513 }
00514 }
00515
00516 static gboolean
00517 qof_entity_guid_match (QofSession * new_session, QofEntity * original)
00518 {
00519 QofEntity *copy;
00520 const GUID *g;
00521 QofIdTypeConst type;
00522 QofBook *targetBook;
00523 QofCollection *coll;
00524
00525 copy = NULL;
00526 g_return_val_if_fail (original != NULL, FALSE);
00527 targetBook = qof_session_get_book (new_session);
00528 g_return_val_if_fail (targetBook != NULL, FALSE);
00529 g = qof_entity_get_guid (original);
00530 type = g_strdup (original->e_type);
00531 coll = qof_book_get_collection (targetBook, type);
00532 copy = qof_collection_lookup_entity (coll, g);
00533 if (copy)
00534 {
00535 return TRUE;
00536 }
00537 return FALSE;
00538 }
00539
00540 static void
00541 qof_entity_list_foreach (gpointer data, gpointer user_data)
00542 {
00543 QofEntityCopyData *qecd;
00544 QofEntity *original;
00545 QofInstance *inst;
00546 QofBook *book;
00547 const GUID *g;
00548
00549 g_return_if_fail (data != NULL);
00550 original = (QofEntity *) data;
00551 g_return_if_fail (user_data != NULL);
00552 qecd = (QofEntityCopyData *) user_data;
00553 if (qof_entity_guid_match (qecd->new_session, original))
00554 {
00555 return;
00556 }
00557 qecd->from = original;
00558 if (!qof_object_compliance (original->e_type, FALSE))
00559 {
00560 qecd->error = TRUE;
00561 return;
00562 }
00563 book = qof_session_get_book (qecd->new_session);
00564 inst =
00565 (QofInstance *) qof_object_new_instance (original->e_type, book);
00566 if (!inst)
00567 {
00568 PERR (" failed to create new entity type=%s.", original->e_type);
00569 qecd->error = TRUE;
00570 return;
00571 }
00572 qecd->to = &inst->entity;
00573 g = qof_entity_get_guid (original);
00574 qof_entity_set_guid (qecd->to, g);
00575 if (qecd->param_list != NULL)
00576 {
00577 g_slist_free (qecd->param_list);
00578 qecd->param_list = NULL;
00579 }
00580 qof_class_param_foreach (original->e_type, qof_entity_param_cb, qecd);
00581 g_slist_foreach (qecd->param_list, qof_entity_foreach_copy, qecd);
00582 }
00583
00584 static void
00585 qof_entity_coll_foreach (QofEntity * original, gpointer user_data)
00586 {
00587 QofEntityCopyData *qecd;
00588 const GUID *g;
00589 QofBook *targetBook;
00590 QofCollection *coll;
00591 QofEntity *copy;
00592
00593 g_return_if_fail (user_data != NULL);
00594 copy = NULL;
00595 qecd = (QofEntityCopyData *) user_data;
00596 targetBook = qof_session_get_book (qecd->new_session);
00597 g = qof_entity_get_guid (original);
00598 coll = qof_book_get_collection (targetBook, original->e_type);
00599 copy = qof_collection_lookup_entity (coll, g);
00600 if (copy)
00601 {
00602 qecd->error = TRUE;
00603 }
00604 }
00605
00606 static void
00607 qof_entity_coll_copy (QofEntity * original, gpointer user_data)
00608 {
00609 QofEntityCopyData *qecd;
00610 QofBook *book;
00611 QofInstance *inst;
00612 const GUID *g;
00613
00614 g_return_if_fail (user_data != NULL);
00615 qecd = (QofEntityCopyData *) user_data;
00616 book = qof_session_get_book (qecd->new_session);
00617 if (!qof_object_compliance (original->e_type, TRUE))
00618 {
00619 return;
00620 }
00621 inst =
00622 (QofInstance *) qof_object_new_instance (original->e_type, book);
00623 qecd->to = &inst->entity;
00624 qecd->from = original;
00625 g = qof_entity_get_guid (original);
00626 qof_entity_set_guid (qecd->to, g);
00627 g_slist_foreach (qecd->param_list, qof_entity_foreach_copy, qecd);
00628 }
00629
00630 gboolean
00631 qof_entity_copy_to_session (QofSession * new_session, QofEntity * original)
00632 {
00633 QofEntityCopyData qecd;
00634 QofInstance *inst;
00635 QofBook *book;
00636
00637 if (!new_session || !original)
00638 return FALSE;
00639 if (qof_entity_guid_match (new_session, original))
00640 return FALSE;
00641 if (!qof_object_compliance (original->e_type, TRUE))
00642 return FALSE;
00643 qof_event_suspend ();
00644 qecd.param_list = NULL;
00645 book = qof_session_get_book (new_session);
00646 qecd.new_session = new_session;
00647 qof_book_set_partial (book);
00648 inst =
00649 (QofInstance *) qof_object_new_instance (original->e_type, book);
00650 qecd.to = &inst->entity;
00651 qecd.from = original;
00652 qof_entity_set_guid (qecd.to, qof_entity_get_guid (original));
00653 qof_class_param_foreach (original->e_type, qof_entity_param_cb, &qecd);
00654 if (g_slist_length (qecd.param_list) == 0)
00655 return FALSE;
00656 g_slist_foreach (qecd.param_list, qof_entity_foreach_copy, &qecd);
00657 g_slist_free (qecd.param_list);
00658 qof_event_resume ();
00659 return TRUE;
00660 }
00661
00662 gboolean
00663 qof_entity_copy_list (QofSession * new_session, GList * entity_list)
00664 {
00665 QofEntityCopyData *qecd;
00666
00667 if (!new_session || !entity_list)
00668 return FALSE;
00669 ENTER (" list=%d", g_list_length (entity_list));
00670 qecd = g_new0 (QofEntityCopyData, 1);
00671 qof_event_suspend ();
00672 qecd->param_list = NULL;
00673 qecd->new_session = new_session;
00674 qof_book_set_partial (qof_session_get_book (new_session));
00675 g_list_foreach (entity_list, qof_entity_list_foreach, qecd);
00676 qof_event_resume ();
00677 if (qecd->error)
00678 PWARN (" some/all entities in the list could not be copied.");
00679 g_free (qecd);
00680 LEAVE (" ");
00681 return TRUE;
00682 }
00683
00684 gboolean
00685 qof_entity_copy_coll (QofSession * new_session,
00686 QofCollection * entity_coll)
00687 {
00688 QofEntityCopyData qecd;
00689
00690 g_return_val_if_fail (new_session, FALSE);
00691 if (!entity_coll)
00692 {
00693 return FALSE;
00694 }
00695 qof_event_suspend ();
00696 qecd.param_list = NULL;
00697 qecd.new_session = new_session;
00698 qof_book_set_partial (qof_session_get_book (qecd.new_session));
00699 qof_collection_foreach (entity_coll, qof_entity_coll_foreach, &qecd);
00700 qof_class_param_foreach (qof_collection_get_type (entity_coll),
00701 qof_entity_param_cb, &qecd);
00702 qof_collection_foreach (entity_coll, qof_entity_coll_copy, &qecd);
00703 if (qecd.param_list != NULL)
00704 {
00705 g_slist_free (qecd.param_list);
00706 }
00707 qof_event_resume ();
00708 return TRUE;
00709 }
00710
00711 struct recurse_s
00712 {
00713 QofSession *session;
00714 gboolean success;
00715 GList *ref_list;
00716 GList *ent_list;
00717 };
00718
00719 static void
00720 recurse_collection_cb (QofEntity * ent, gpointer user_data)
00721 {
00722 struct recurse_s *store;
00723
00724 if (user_data == NULL)
00725 {
00726 return;
00727 }
00728 store = (struct recurse_s *) user_data;
00729 if (!ent || !store)
00730 {
00731 return;
00732 }
00733 store->success = qof_entity_copy_to_session (store->session, ent);
00734 if (store->success)
00735 {
00736 store->ent_list = g_list_append (store->ent_list, ent);
00737 }
00738 }
00739
00740 static void
00741 recurse_ent_cb (QofEntity * ent, gpointer user_data)
00742 {
00743 GList *ref_list, *i, *j, *ent_list, *child_list;
00744 QofParam *ref_param;
00745 QofEntity *ref_ent, *child_ent;
00746 QofSession *session;
00747 struct recurse_s *store;
00748 gboolean success;
00749
00750 if (user_data == NULL)
00751 {
00752 return;
00753 }
00754 store = (struct recurse_s *) user_data;
00755 session = store->session;
00756 success = store->success;
00757 ref_list = NULL;
00758 child_ent = NULL;
00759 ref_list = g_list_copy (store->ref_list);
00760 if ((!session) || (!ent))
00761 {
00762 return;
00763 }
00764 ent_list = NULL;
00765 child_list = NULL;
00766 i = NULL;
00767 j = NULL;
00768 for (i = ref_list; i != NULL; i = i->next)
00769 {
00770 if (i->data == NULL)
00771 {
00772 continue;
00773 }
00774 ref_param = (QofParam *) i->data;
00775 if (ref_param->param_name == NULL)
00776 {
00777 continue;
00778 }
00779 if (0 == safe_strcmp (ref_param->param_type, QOF_TYPE_COLLECT))
00780 {
00781 QofCollection *col;
00782
00783 col = ref_param->param_getfcn (ent, ref_param);
00784 if (col)
00785 {
00786 qof_collection_foreach (col, recurse_collection_cb, store);
00787 }
00788 continue;
00789 }
00790 ref_ent = (QofEntity *) ref_param->param_getfcn (ent, ref_param);
00791 if ((ref_ent) && (ref_ent->e_type))
00792 {
00793 store->success = qof_entity_copy_to_session (session, ref_ent);
00794 if (store->success)
00795 {
00796 ent_list = g_list_append (ent_list, ref_ent);
00797 }
00798 }
00799 }
00800 for (i = ent_list; i != NULL; i = i->next)
00801 {
00802 if (i->data == NULL)
00803 {
00804 continue;
00805 }
00806 child_ent = (QofEntity *) i->data;
00807 if (child_ent == NULL)
00808 {
00809 continue;
00810 }
00811 ref_list = qof_class_get_referenceList (child_ent->e_type);
00812 for (j = ref_list; j != NULL; j = j->next)
00813 {
00814 if (j->data == NULL)
00815 {
00816 continue;
00817 }
00818 ref_param = (QofParam *) j->data;
00819 ref_ent = ref_param->param_getfcn (child_ent, ref_param);
00820 if (ref_ent != NULL)
00821 {
00822 success = qof_entity_copy_to_session (session, ref_ent);
00823 if (success)
00824 {
00825 child_list = g_list_append (child_list, ref_ent);
00826 }
00827 }
00828 }
00829 }
00830 for (i = child_list; i != NULL; i = i->next)
00831 {
00832 if (i->data == NULL)
00833 {
00834 continue;
00835 }
00836 ref_ent = (QofEntity *) i->data;
00837 if (ref_ent == NULL)
00838 {
00839 continue;
00840 }
00841 ref_list = qof_class_get_referenceList (ref_ent->e_type);
00842 for (j = ref_list; j != NULL; j = j->next)
00843 {
00844 if (j->data == NULL)
00845 {
00846 continue;
00847 }
00848 ref_param = (QofParam *) j->data;
00849 child_ent = ref_param->param_getfcn (ref_ent, ref_param);
00850 if (child_ent != NULL)
00851 {
00852 qof_entity_copy_to_session (session, child_ent);
00853 }
00854 }
00855 }
00856 }
00857
00858 gboolean
00859 qof_entity_copy_coll_r (QofSession * new_session, QofCollection * coll)
00860 {
00861 struct recurse_s store;
00862 gboolean success;
00863
00864 if ((!new_session) || (!coll))
00865 {
00866 return FALSE;
00867 }
00868 store.session = new_session;
00869 success = TRUE;
00870 store.success = success;
00871 store.ent_list = NULL;
00872 store.ref_list =
00873 qof_class_get_referenceList (qof_collection_get_type (coll));
00874 success = qof_entity_copy_coll (new_session, coll);
00875 if (success)
00876 {
00877 qof_collection_foreach (coll, recurse_ent_cb, &store);
00878 }
00879 return success;
00880 }
00881
00882 gboolean
00883 qof_entity_copy_one_r (QofSession * new_session, QofEntity * ent)
00884 {
00885 struct recurse_s store;
00886 QofCollection *coll;
00887 gboolean success;
00888
00889 if ((!new_session) || (!ent))
00890 {
00891 return FALSE;
00892 }
00893 store.session = new_session;
00894 success = TRUE;
00895 store.success = success;
00896 store.ref_list = qof_class_get_referenceList (ent->e_type);
00897 success = qof_entity_copy_to_session (new_session, ent);
00898 if (success == TRUE)
00899 {
00900 coll =
00901 qof_book_get_collection (qof_session_get_book (new_session),
00902 ent->e_type);
00903 if (coll)
00904 {
00905 qof_collection_foreach (coll, recurse_ent_cb, &store);
00906 }
00907 }
00908 return success;
00909 }
00910
00911
00912
00913
00917 struct backend_providers
00918 {
00919 const gchar *libdir;
00920 const gchar *filename;
00921 const gchar *init_fcn;
00922 };
00923
00924
00925
00926
00927
00928 struct backend_providers backend_list[] = {
00929 {QOF_LIB_DIR, QSF_BACKEND_LIB, QSF_MODULE_INIT},
00930 {QOF_LIB_DIR, "libqof-backend-sqlite", "qof_sqlite_provider_init"},
00931 #ifdef HAVE_GDA
00932 {QOF_LIB_DIR, "libqof-backend-gda", "qof_gda_provider_init"},
00933 #endif
00934 #ifdef HAVE_ESTRON
00935 {QOF_LIB_DIR, "libqof_backend_estron", "dwiend_provider_init"},
00936 #endif
00937 {NULL, NULL, NULL}
00938 };
00939
00940 static void
00941 qof_session_load_backend (QofSession * session, gchar *access_method)
00942 {
00943 GSList *p;
00944 GList *node;
00945 QofBackendProvider *prov;
00946 QofBook *book;
00947 gint num;
00948 gboolean prov_type;
00949 gboolean (*type_check) (const gchar *);
00950
00951 ENTER (" list=%d", g_slist_length (provider_list));
00952 prov_type = FALSE;
00953 if (NULL == provider_list)
00954 {
00955 for (num = 0; backend_list[num].filename != NULL; num++)
00956 {
00957 if (!qof_load_backend_library (backend_list[num].libdir,
00958 backend_list[num].filename,
00959 backend_list[num].init_fcn))
00960 {
00961 PWARN (" failed to load %s from %s using %s",
00962 backend_list[num].filename, backend_list[num].libdir,
00963 backend_list[num].init_fcn);
00964 }
00965 }
00966 }
00967 p = g_slist_copy (provider_list);
00968 while (p != NULL)
00969 {
00970 prov = p->data;
00971
00972 if (0 == strcasecmp (access_method, prov->access_method))
00973 {
00974
00975
00976 type_check =
00977 (gboolean (*)(const gchar *)) prov->check_data_type;
00978 prov_type = (type_check) (session->book_id);
00979 if (!prov_type)
00980 {
00981 PINFO (" %s not usable", prov->provider_name);
00982 p = p->next;
00983 continue;
00984 }
00985 PINFO (" selected %s", prov->provider_name);
00986 if (NULL == prov->backend_new)
00987 {
00988 p = p->next;
00989 continue;
00990 }
00991
00992 session->backend = (*(prov->backend_new)) ();
00993 session->backend->provider = prov;
00994
00995 for (node = session->books; node; node = node->next)
00996 {
00997 book = node->data;
00998 qof_book_set_backend (book, session->backend);
00999 }
01000 LEAVE (" ");
01001 return;
01002 }
01003 p = p->next;
01004 }
01005 LEAVE (" ");
01006 }
01007
01008
01009
01010 static void
01011 qof_session_destroy_backend (QofSession * session)
01012 {
01013 g_return_if_fail (session);
01014
01015 if (session->backend)
01016 {
01017
01018 if (session->backend->destroy_backend)
01019 {
01020 session->backend->destroy_backend (session->backend);
01021 }
01022 else
01023 {
01024 g_free (session->backend);
01025 }
01026 }
01027
01028 session->backend = NULL;
01029 }
01030
01031 void
01032 qof_session_begin (QofSession * session, const gchar *book_id,
01033 gboolean ignore_lock, gboolean create_if_nonexistent)
01034 {
01035 gchar *p, *access_method;
01036
01037 if (!session)
01038 return;
01039
01040 ENTER (" sess=%p ignore_lock=%d, book-id=%s",
01041 session, ignore_lock, book_id ? book_id : "(null)");
01042
01043
01044 qof_error_clear (session);
01045
01046
01047 if (session->book_id)
01048 {
01049 qof_error_set (session, qof_error_register
01050 (_("This book appears to be open already."), FALSE));
01051 LEAVE (" push error book is already open ");
01052 return;
01053 }
01054
01055 if (!book_id)
01056 {
01057 LEAVE (" using stdout");
01058 return;
01059 }
01060
01061
01062 session->book_id = g_strdup (book_id);
01063
01064
01065 qof_session_destroy_backend (session);
01066
01067
01068
01069
01070
01071 p = strchr (book_id, ':');
01072 if (p)
01073 {
01074 access_method = g_strdup (book_id);
01075 p = strchr (access_method, ':');
01076 *p = 0;
01077 qof_session_load_backend (session, access_method);
01078 g_free (access_method);
01079 }
01080 else
01081 {
01082
01083 qof_session_load_backend (session, "file");
01084 }
01085
01086
01087 if (NULL == session->backend)
01088 {
01089 gchar * msg;
01090
01091 msg = g_strdup_printf (_("Unable to locate a "
01092 "suitable backend for '%s' - please check "
01093 "you have specified an access method "
01094 "like file: or sqlite:"), book_id);
01095 qof_error_set (session, qof_error_register
01096 (msg, FALSE));
01097 DEBUG (" msg=%s", msg);
01098 LEAVE (" BAD: no backend: sess=%p book-id=%s",
01099 session, book_id ? book_id : "(null)");
01100 g_free (msg);
01101 return;
01102 }
01103
01104
01105 if (session->backend->session_begin)
01106 {
01107 (session->backend->session_begin) (session->backend, session,
01108 session->book_id, ignore_lock, create_if_nonexistent);
01109 PINFO (" Done running session_begin on backend");
01110 if (qof_error_check(session) != QOF_SUCCESS)
01111 {
01112 g_free (session->book_id);
01113 session->book_id = NULL;
01114 LEAVE (" backend error ");
01115 return;
01116 }
01117 }
01118 qof_error_clear (session);
01119 LEAVE (" sess=%p book-id=%s", session, book_id ? book_id : "(null)");
01120 }
01121
01122
01123
01124 void
01125 qof_session_load (QofSession * session, QofPercentageFunc percentage_func)
01126 {
01127 QofBook *newbook, *ob;
01128 QofBookList *oldbooks, *node;
01129 QofBackend *be;
01130
01131 if (!session)
01132 return;
01133 if ((!session->book_id) ||
01134 (0 == safe_strcasecmp(session->book_id, QOF_STDOUT)))
01135 return;
01136
01137 ENTER (" sess=%p book_id=%s", session, session->book_id
01138 ? session->book_id : "(null)");
01139
01140
01141
01142
01143 oldbooks = session->books;
01144
01145
01146
01147
01148
01149 newbook = qof_book_new ();
01150 session->books = g_list_append (NULL, newbook);
01151 PINFO (" new book=%p", newbook);
01152
01153 qof_error_clear (session);
01154
01155
01156
01157
01158
01159
01160
01161
01162 be = session->backend;
01163 qof_book_set_backend (newbook, be);
01164
01165
01166
01167
01168
01169 if (be)
01170 {
01171 be->percentage = percentage_func;
01172
01173 if (be->load)
01174 {
01175 be->load (be, newbook);
01176 }
01177 }
01178
01179 if (qof_error_check(session) != QOF_SUCCESS)
01180 {
01181
01182 qof_book_set_backend (newbook, NULL);
01183 qof_book_destroy (newbook);
01184 g_list_free (session->books);
01185 session->books = oldbooks;
01186 g_free (session->book_id);
01187 session->book_id = NULL;
01188 LEAVE (" error from backend ");
01189 return;
01190 }
01191
01192 for (node = oldbooks; node; node = node->next)
01193 {
01194 ob = node->data;
01195 qof_book_set_backend (ob, NULL);
01196 qof_book_destroy (ob);
01197 }
01198 g_list_free (oldbooks);
01199
01200 LEAVE (" sess = %p, book_id=%s", session, session->book_id
01201 ? session->book_id : "(null)");
01202 }
01203
01204
01205
01206 gboolean
01207 qof_session_save_may_clobber_data (QofSession * session)
01208 {
01209 if (!session)
01210 return FALSE;
01211 if (!session->backend)
01212 return FALSE;
01213 if (!session->backend->save_may_clobber_data)
01214 return FALSE;
01215
01216 return (*(session->backend->save_may_clobber_data)) (session->backend);
01217 }
01218
01219 void
01220 qof_session_save (QofSession * session,
01221 QofPercentageFunc percentage_func)
01222 {
01223 GList *node;
01224 QofBackend *be;
01225 gboolean partial, change_backend;
01226 QofBackendProvider *prov;
01227 GSList *p;
01228 QofBook *book, *abook;
01229 gint num;
01230 gchar *msg, *book_id;
01231
01232 if (!session)
01233 return;
01234 ENTER (" sess=%p book_id=%s",
01235 session, session->book_id ? session->book_id : "(null)");
01236
01237 book = qof_session_get_book (session);
01238 partial =
01239 (gboolean)
01240 GPOINTER_TO_INT (qof_book_get_data (book, PARTIAL_QOFBOOK));
01241 change_backend = FALSE;
01242 msg = g_strdup_printf (" ");
01243 book_id = g_strdup (session->book_id);
01244 if (partial == TRUE)
01245 {
01246 if (session->backend && session->backend->provider)
01247 {
01248 prov = session->backend->provider;
01249 if (TRUE == prov->partial_book_supported)
01250 {
01251
01252 change_backend = FALSE;
01253 }
01254 else
01255 {
01256 change_backend = TRUE;
01257 }
01258 }
01259
01260 else
01261 {
01262 change_backend = TRUE;
01263 }
01264 }
01265 if (change_backend == TRUE)
01266 {
01267 qof_session_destroy_backend (session);
01268 if (NULL == provider_list)
01269 {
01270 for (num = 0; backend_list[num].filename != NULL; num++)
01271 {
01272 qof_load_backend_library (backend_list[num].libdir,
01273 backend_list[num].filename,
01274 backend_list[num].init_fcn);
01275 }
01276 }
01277 p = g_slist_copy (provider_list);
01278 while (p != NULL)
01279 {
01280 prov = p->data;
01281 if (TRUE == prov->partial_book_supported)
01282 {
01284
01285
01286
01287 if (NULL == prov->backend_new)
01288 continue;
01289
01290 session->backend = (*(prov->backend_new)) ();
01291 session->backend->provider = prov;
01292 if (session->backend->session_begin)
01293 {
01294
01295
01296
01297 g_free (session->book_id);
01298 session->book_id = NULL;
01299 (session->backend->session_begin) (session->backend,
01300 session, book_id, TRUE, TRUE);
01301 PINFO
01302 (" Done running session_begin on changed backend");
01303 if (qof_error_check (session) != QOF_SUCCESS)
01304 {
01305 g_free (session->book_id);
01306 session->book_id = NULL;
01307 LEAVE (" changed backend error");
01308 return;
01309 }
01310 }
01311
01312 for (node = session->books; node; node = node->next)
01313 {
01314 book = node->data;
01315 qof_book_set_backend (book, session->backend);
01316 }
01317 p = NULL;
01318 }
01319 if (p)
01320 {
01321 p = p->next;
01322 }
01323 }
01324 if (!session->backend)
01325 {
01326 msg = g_strdup_printf (" failed to load backend");
01327 qof_error_set (session, qof_error_register
01328 (_("Failed to load backend, no suitable handler."),
01329 FALSE));
01330 return;
01331 }
01332 }
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342 be = session->backend;
01343 if (be)
01344 {
01345 for (node = session->books; node; node = node->next)
01346 {
01347 abook = node->data;
01348
01349 qof_book_set_backend (abook, be);
01350 be->percentage = percentage_func;
01351 if (be->sync)
01352 (be->sync) (be, abook);
01353 }
01354
01355
01356
01357 qof_error_clear (session);
01358 LEAVE (" Success");
01359 return;
01360 }
01361 else
01362 {
01363 msg = g_strdup_printf (" failed to load backend");
01364 qof_error_set (session, qof_error_register
01365 (_("Failed to load backend, no suitable handler."),
01366 FALSE));
01367 }
01368 LEAVE (" error -- No backend!");
01369 }
01370
01371
01372
01373 void
01374 qof_session_end (QofSession * session)
01375 {
01376 if (!session)
01377 return;
01378
01379 ENTER (" sess=%p book_id=%s", session, session->book_id
01380 ? session->book_id : "(null)");
01381
01382
01383 if (session->backend && session->backend->session_end)
01384 {
01385 (session->backend->session_end) (session->backend);
01386 }
01387
01388 qof_error_clear (session);
01389
01390 g_free (session->book_id);
01391 session->book_id = NULL;
01392
01393 LEAVE (" sess=%p book_id=%s", session, session->book_id
01394 ? session->book_id : "(null)");
01395 }
01396
01397 void
01398 qof_session_destroy (QofSession * session)
01399 {
01400 GList *node;
01401 if (!session)
01402 return;
01403
01404 ENTER (" sess=%p book_id=%s", session, session->book_id
01405 ? session->book_id : "(null)");
01406
01407 qof_session_end (session);
01408
01409
01410 qof_session_destroy_backend (session);
01411
01412 for (node = session->books; node; node = node->next)
01413 {
01414 QofBook *book = node->data;
01415 qof_book_set_backend (book, NULL);
01416 qof_book_destroy (book);
01417 }
01418
01419 session->books = NULL;
01420 g_free (session);
01421 qof_error_close ();
01422
01423 LEAVE (" sess=%p", session);
01424 }
01425
01426
01427
01428 void
01429 qof_session_swap_data (QofSession * session_1, QofSession * session_2)
01430 {
01431 GList *books_1, *books_2, *node;
01432
01433 if (session_1 == session_2)
01434 return;
01435 if (!session_1 || !session_2)
01436 return;
01437
01438 ENTER (" sess1=%p sess2=%p", session_1, session_2);
01439
01440 books_1 = session_1->books;
01441 books_2 = session_2->books;
01442
01443 session_1->books = books_2;
01444 session_2->books = books_1;
01445
01446 for (node = books_1; node; node = node->next)
01447 {
01448 QofBook *book_1 = node->data;
01449 qof_book_set_backend (book_1, session_2->backend);
01450 }
01451 for (node = books_2; node; node = node->next)
01452 {
01453 QofBook *book_2 = node->data;
01454 qof_book_set_backend (book_2, session_1->backend);
01455 }
01456
01457 LEAVE (" ");
01458 }
01459
01460
01461
01462 gboolean
01463 qof_session_events_pending (QofSession * session)
01464 {
01465 if (!session)
01466 return FALSE;
01467 if (!session->backend)
01468 return FALSE;
01469 if (!session->backend->events_pending)
01470 return FALSE;
01471
01472 return session->backend->events_pending (session->backend);
01473 }
01474
01475 gboolean
01476 qof_session_process_events (QofSession * session)
01477 {
01478 if (!session)
01479 return FALSE;
01480 if (!session->backend)
01481 return FALSE;
01482 if (!session->backend->process_events)
01483 return FALSE;
01484
01485 return session->backend->process_events (session->backend);
01486 }
01487
01488