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