r20514 - gnucash/trunk - Remove the qof_book_merge code because it is unused in gnucash.
Christian Stimming
cstim at code.gnucash.org
Sat Apr 2 15:59:20 EDT 2011
Author: cstim
Date: 2011-04-02 15:59:20 -0400 (Sat, 02 Apr 2011)
New Revision: 20514
Trac: http://svn.gnucash.org/trac/changeset/20514
Removed:
gnucash/trunk/src/engine/test/test-book-merge.c
gnucash/trunk/src/libqof/qof/qofbookmerge.c
gnucash/trunk/src/libqof/qof/qofbookmerge.h
Modified:
gnucash/trunk/po/POTFILES.in
gnucash/trunk/src/engine/test/Makefile.am
gnucash/trunk/src/libqof/CMakeLists.txt
gnucash/trunk/src/libqof/qof/Makefile.am
gnucash/trunk/src/libqof/qof/qof.h
Log:
Remove the qof_book_merge code because it is unused in gnucash.
Modified: gnucash/trunk/po/POTFILES.in
===================================================================
--- gnucash/trunk/po/POTFILES.in 2011-04-02 19:59:06 UTC (rev 20513)
+++ gnucash/trunk/po/POTFILES.in 2011-04-02 19:59:20 UTC (rev 20514)
@@ -422,7 +422,6 @@
src/libqof/qof/md5.c
src/libqof/qof/qofbackend.c
src/libqof/qof/qofbook.c
-src/libqof/qof/qofbookmerge.c
src/libqof/qof/qofchoice.c
src/libqof/qof/qofclass.c
src/libqof/qof/qofevent.c
Modified: gnucash/trunk/src/engine/test/Makefile.am
===================================================================
--- gnucash/trunk/src/engine/test/Makefile.am 2011-04-02 19:59:06 UTC (rev 20513)
+++ gnucash/trunk/src/engine/test/Makefile.am 2011-04-02 19:59:20 UTC (rev 20514)
@@ -43,8 +43,7 @@
test-transaction-reversal \
test-transaction-voiding \
test-recurrence \
- test-scm-query \
- test-book-merge
+ test-scm-query
GNC_TEST_DEPS = \
--gnc-module-dir ${top_builddir}/src/engine \
@@ -71,7 +70,6 @@
test-period \
test-lots \
test-numeric \
- test-book-merge \
test-object \
test-query \
test-querynew \
Deleted: gnucash/trunk/src/engine/test/test-book-merge.c
===================================================================
--- gnucash/trunk/src/engine/test/test-book-merge.c 2011-04-02 19:59:06 UTC (rev 20513)
+++ gnucash/trunk/src/engine/test/test-book-merge.c 2011-04-02 19:59:20 UTC (rev 20514)
@@ -1,534 +0,0 @@
-/*********************************************************************
- * test-book-merge.c -- test implementation api for QoFBook merge *
- * Copyright (C) 2004-2005 Neil Williams <linux at codehelp.co.uk> *
- * *
- * This program is free software; you can redistribute it and/or *
- * modify it under the terms of the GNU General Public License as *
- * published by the Free Software Foundation; either version 2 of *
- * the License, or (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, contact: *
- * *
- * Free Software Foundation Voice: +1-617-542-5942 *
- * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
- * Boston, MA 02110-1301, USA gnu at gnu.org *
- * *
- ********************************************************************/
-/* Test the qof_book_merge infrastructure. */
-
-#include "config.h"
-#include <glib.h>
-
-#include "qof.h"
-#include "test-stuff.h"
-#include "gnc-engine.h"
-
-#define TEST_MODULE_NAME "book-merge-test"
-#define TEST_MODULE_DESC "Test Book Merge"
-#define OBJ_NAME "somename"
-#define OBJ_AMOUNT "anamount"
-#define OBJ_DATE "nottoday"
-#define OBJ_GUID "unique"
-#define OBJ_DISCOUNT "hefty"
-#define OBJ_VERSION "early"
-#define OBJ_MINOR "tiny"
-#define OBJ_ACTIVE "ofcourse"
-
-static void test_rule_loop (QofBookMergeData*, QofBookMergeRule*, guint);
-static void test_merge (void);
-gboolean myobjRegister (void);
-
-/* simple object structure */
-typedef struct obj_s
-{
- QofInstance inst;
- char *Name;
- gnc_numeric Amount;
- const GncGUID *obj_guid;
- Timespec date;
- double discount; /* cheap pun, I know. */
- gboolean active;
- gint32 version;
- gint64 minor;
-} myobj;
-
-typedef struct objclass_s
-{
- QofInstanceClass parent_class;
-} myobjClass;
-
-myobj* obj_create(QofBook*);
-
-/* obvious setter functions */
-void obj_setName(myobj*, char*);
-void obj_setGUID(myobj*, const GncGUID*);
-void obj_setAmount(myobj*, gnc_numeric);
-void obj_setDate(myobj*, Timespec h);
-void obj_setDiscount(myobj*, double);
-void obj_setActive(myobj*, gboolean);
-void obj_setVersion(myobj*, gint32);
-void obj_setMinor(myobj*, gint64);
-
-/* obvious getter functions */
-char* obj_getName(myobj*);
-const GncGUID* obj_getGUID(myobj*);
-gnc_numeric obj_getAmount(myobj*);
-Timespec obj_getDate(myobj*);
-double obj_getDiscount(myobj*);
-gboolean obj_getActive(myobj*);
-gint32 obj_getVersion(myobj*);
-gint64 obj_getMinor(myobj*);
-
-/* --- type macros --- */
-#define GNC_TYPE_MYOBJ (gnc_myobj_get_type ())
-#define GNC_MYOBJ(o) \
- (G_TYPE_CHECK_INSTANCE_CAST ((o), GNC_TYPE_MYOBJ, myobj))
-#define GNC_MYOBJ_CLASS(k) \
- (G_TYPE_CHECK_CLASS_CAST((k), GNC_TYPE_MYOBJ, myobjClass))
-#define GNC_IS_MYOBJ(o) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((o), GNC_TYPE_MYOBJ))
-#define GNC_IS_MYOBJ_CLASS(k) \
- (G_TYPE_CHECK_CLASS_TYPE ((k), GNC_TYPE_MYOBJ))
-#define GNC_MYOBJ_GET_CLASS(o) \
- (G_TYPE_INSTANCE_GET_CLASS ((o), GNC_TYPE_MYOBJ, myobjClass))
-GType gnc_myobj_get_type(void);
-
-/* GObject Initialization */
-QOF_GOBJECT_IMPL(gnc_myobj, myobj, QOF_TYPE_INSTANCE);
-
-static void
-gnc_myobj_init(myobj* obj)
-{
-}
-
-static void
-gnc_myobj_dispose_real (GObject *objp)
-{
-}
-
-static void
-gnc_myobj_finalize_real(GObject* objp)
-{
-}
-
-myobj*
-obj_create(QofBook *book)
-{
- myobj *g;
- g_return_val_if_fail(book, NULL);
- g = g_object_new(GNC_TYPE_MYOBJ, NULL);
- qof_instance_init_data (&g->inst, TEST_MODULE_NAME, book);
- obj_setGUID(g, qof_instance_get_guid(&g->inst));
- g->date.tv_nsec = 0;
- g->date.tv_sec = 0;
- g->discount = 0;
- g->active = TRUE;
- g->version = 1;
- g->minor = 1;
- qof_event_gen(&g->inst, QOF_EVENT_CREATE, NULL);
- return g;
-}
-
-void
-obj_setMinor(myobj *g, gint64 h)
-{
- g_return_if_fail(g != NULL);
- g->minor = h;
-}
-
-gint64
-obj_getMinor(myobj *g)
-{
- g_return_val_if_fail((g != NULL), 0);
- return g->minor;
-}
-
-void
-obj_setVersion(myobj *g, gint32 h)
-{
- g_return_if_fail(g != NULL);
- g->version = h;
-}
-
-gint32
-obj_getVersion(myobj *g)
-{
- if (!g) return 0;
- return g->version;
-}
-
-void
-obj_setActive(myobj *g, gboolean h)
-{
- if (!g) return;
- g->active = h;
-}
-
-gboolean
-obj_getActive(myobj *g)
-{
- if (!g) return FALSE;
- return g->active;
-}
-
-void
-obj_setDiscount(myobj *g, double h)
-{
- if (!g) return;
- g->discount = h;
-}
-
-double
-obj_getDiscount(myobj *g)
-{
- if (!g) return 0;
- return g->discount;
-}
-
-void
-obj_setDate(myobj *g, Timespec h)
-{
- if (!g) return;
- g->date = h;
-}
-
-Timespec
-obj_getDate(myobj *g)
-{
- Timespec ts = {0};
- if (!g) return ts;
- ts = g->date;
- return ts;
-}
-
-void
-obj_setGUID(myobj* g, const GncGUID* h)
-{
- if (!g) return;
- g->obj_guid = h;
-}
-
-const GncGUID*
-obj_getGUID(myobj *g)
-{
- if (!g) return NULL;
- return g->obj_guid;
-}
-
-void
-obj_setName(myobj* g, char* h)
-{
- if (!g || !h) return;
- g->Name = strdup(h);
-}
-
-char*
-obj_getName(myobj *g)
-{
- if (!g) return NULL;
- return g->Name;
-}
-
-void
-obj_setAmount(myobj *g, gnc_numeric h)
-{
- if (!g) return;
- g->Amount = h;
-}
-
-gnc_numeric
-obj_getAmount(myobj *g)
-{
- if (!g) return gnc_numeric_zero();
- return g->Amount;
-}
-
-static QofObject obj_object_def =
-{
-interface_version:
- QOF_OBJECT_VERSION,
-e_type:
- TEST_MODULE_NAME,
-type_label:
- TEST_MODULE_DESC,
-create:
- (gpointer)obj_create,
-book_begin:
- NULL,
-book_end:
- NULL,
-is_dirty:
- NULL,
-mark_clean:
- NULL,
-foreach:
- qof_collection_foreach,
-printable:
- NULL,
-version_cmp:
- (int (*)(gpointer, gpointer)) qof_instance_version_cmp,
-};
-
-gboolean myobjRegister (void)
-{
- static QofParam params[] =
- {
- { OBJ_NAME, QOF_TYPE_STRING, (QofAccessFunc)obj_getName, (QofSetterFunc)obj_setName },
- { OBJ_AMOUNT, QOF_TYPE_NUMERIC, (QofAccessFunc)obj_getAmount, (QofSetterFunc)obj_setAmount },
- { OBJ_GUID, QOF_TYPE_GUID, (QofAccessFunc)obj_getGUID, (QofSetterFunc)obj_setGUID },
- { OBJ_DATE, QOF_TYPE_DATE, (QofAccessFunc)obj_getDate, (QofSetterFunc)obj_setDate },
- { OBJ_DISCOUNT, QOF_TYPE_DOUBLE, (QofAccessFunc)obj_getDiscount, (QofSetterFunc)obj_setDiscount },
- { OBJ_ACTIVE, QOF_TYPE_BOOLEAN, (QofAccessFunc)obj_getActive, (QofSetterFunc)obj_setActive },
- { OBJ_VERSION, QOF_TYPE_INT32, (QofAccessFunc)obj_getVersion, (QofSetterFunc)obj_setVersion },
- { OBJ_MINOR, QOF_TYPE_INT64, (QofAccessFunc)obj_getMinor, (QofSetterFunc)obj_setMinor },
- { QOF_PARAM_BOOK, QOF_ID_BOOK, (QofAccessFunc)qof_instance_get_book, NULL },
- { QOF_PARAM_GUID, QOF_TYPE_GUID, (QofAccessFunc)qof_instance_get_guid, NULL },
- { NULL },
- };
-
- qof_class_register (TEST_MODULE_NAME, NULL, params);
-
- return qof_object_register (&obj_object_def);
-}
-
-static void
-test_merge (void)
-{
- QofBook *target, *import;
- double init_value, discount;
- myobj *import_obj, *target_obj, *new_obj;
- int result;
- Timespec ts, tc;
- gboolean active;
- gint32 version;
- gint64 minor;
- gchar *import_init, *target_init;
- gnc_numeric obj_amount;
- QofBookMergeData *mergeData;
-
- target = qof_book_new();
- import = qof_book_new();
- init_value = 1.00;
- result = 0;
- discount = 0.5;
- active = TRUE;
- version = 1;
- minor = 1;
- import_init = "test";
- target_init = "testing";
- qof_date_format_set(QOF_DATE_FORMAT_UK);
- timespecFromTime_t(&ts, time(NULL));
-
- do_test ((NULL != target), "#1 target book is NULL");
-
- /* import book objects - tests used */
- do_test ((NULL != import), "#2 import book is NULL");
- import_obj = g_object_new(GNC_TYPE_MYOBJ, NULL);
- do_test ((NULL != import_obj), "#3 new object create");
- qof_instance_init_data (&import_obj->inst, TEST_MODULE_NAME, import);
- do_test ((NULL != &import_obj->inst), "#4 instance init");
- obj_setGUID(import_obj, qof_instance_get_guid(&import_obj->inst));
- do_test ((NULL != &import_obj->obj_guid), "#5 guid set");
- qof_event_gen(&import_obj->inst, QOF_EVENT_CREATE, NULL);
- do_test ((NULL != &import_obj->inst), "#6 gnc event create");
- obj_setName(import_obj, import_init);
- do_test ((NULL != &import_obj->Name), "#7 string set");
- obj_amount = double_to_gnc_numeric(init_value, 1, GNC_HOW_DENOM_EXACT);
- obj_setAmount(import_obj, obj_amount);
- do_test ((gnc_numeric_check(obj_getAmount(import_obj)) == GNC_ERROR_OK), "#8 gnc_numeric set");
- obj_setActive(import_obj, active);
- do_test ((FALSE != &import_obj->active), "#9 gboolean set");
- obj_setDiscount(import_obj, discount);
- do_test ((discount == import_obj->discount), "#10 double set");
- obj_setVersion(import_obj, version);
- do_test ((version == import_obj->version), "#11 gint32 set");
- obj_setMinor(import_obj, minor);
- do_test ((minor == import_obj->minor), "#12 gint64 set");
- obj_setDate(import_obj, ts );
- tc = import_obj->date;
- do_test ((timespec_cmp(&ts, &tc) == 0), "#13 date set");
-
- obj_amount = gnc_numeric_add(obj_amount, obj_amount, 1, GNC_HOW_DENOM_EXACT);
- discount = 0.25;
- version = 2;
- minor = 3;
-
- /* second import object - test results would be the same, so not tested. */
- new_obj = g_object_new(GNC_TYPE_MYOBJ, NULL);
- qof_instance_init_data (&new_obj->inst, TEST_MODULE_NAME, import);
- obj_setGUID(new_obj, qof_instance_get_guid(&new_obj->inst));
- qof_event_gen (&new_obj->inst, QOF_EVENT_CREATE, NULL);
- obj_setName(new_obj, import_init);
- obj_setAmount(new_obj, obj_amount);
- obj_setActive(new_obj, active);
- obj_setDiscount(new_obj, discount);
- obj_setVersion(new_obj, version);
- obj_setMinor(new_obj, minor);
- obj_setDate(new_obj, ts);
-
- obj_amount = gnc_numeric_add(obj_amount, obj_amount, 1, GNC_HOW_DENOM_EXACT);
- discount = 0.35;
- version = 2;
- minor = 3;
- tc.tv_sec = ts.tv_sec - 1;
- tc.tv_nsec = 0;
-
- /* target object - test results would be the same, so not tested. */
- target_obj = g_object_new(GNC_TYPE_MYOBJ, NULL);
- qof_instance_init_data (&target_obj->inst, TEST_MODULE_NAME, target);
- obj_setGUID(target_obj, qof_instance_get_guid(&target_obj->inst));
- qof_event_gen (&target_obj->inst, QOF_EVENT_CREATE, NULL);
- obj_setName(target_obj, target_init);
- obj_setAmount(target_obj, obj_amount);
- obj_setActive(target_obj, active);
- obj_setDiscount(target_obj, discount);
- obj_setVersion(target_obj, version);
- obj_setMinor(target_obj, minor);
- obj_setDate(target_obj, tc );
-
- mergeData = qof_book_merge_init(import, target);
- do_test ( mergeData != NULL, "FATAL: Merge could not be initialised!\t aborting . . ");
- g_return_if_fail(mergeData != NULL);
- qof_book_merge_rule_foreach(mergeData, test_rule_loop, MERGE_REPORT);
- qof_book_merge_rule_foreach(mergeData, test_rule_loop, MERGE_UPDATE);
- qof_book_merge_rule_foreach(mergeData, test_rule_loop, MERGE_NEW);
- /* reserved calls - test only */
- qof_book_merge_rule_foreach(mergeData, test_rule_loop, MERGE_ABSOLUTE);
- qof_book_merge_rule_foreach(mergeData, test_rule_loop, MERGE_DUPLICATE);
-
- /* import should not be in the target - pass if import_init fails match with target */
- do_test (((safe_strcmp(obj_getName(import_obj), obj_getName(target_obj))) != 0), "Init value test #1");
-
- /* a good commit returns zero */
- do_test (qof_book_merge_commit(mergeData) == 0, "Commit failed");
-
- /* import should be in the target - pass if import_init matches target */
- do_test (((safe_strcmp(import_init, obj_getName(target_obj))) == 0), "Merged value test #1");
-
- /* import should be the same as target - pass if values are the same */
- do_test (((safe_strcmp(obj_getName(target_obj), obj_getName(import_obj))) == 0), "Merged value test #2");
-
- /* check that the Amount really is a gnc_numeric */
- do_test ((gnc_numeric_check(obj_getAmount(import_obj)) == GNC_ERROR_OK), "import gnc_numeric check");
- do_test ((gnc_numeric_check(obj_getAmount(target_obj)) == GNC_ERROR_OK), "target gnc_numeric check");
-
- /* obj_amount was changed after the import object was set, so expect a difference. */
- do_test ((gnc_numeric_compare(obj_getAmount(import_obj), obj_amount) != GNC_ERROR_OK),
- "gnc_numeric value check #1");
-
- /* obj_amount is in the target object with the import value, expect a difference/ */
- do_test ((gnc_numeric_compare(obj_getAmount(target_obj), obj_amount) != GNC_ERROR_OK),
- "gnc_numeric value check #2");
-
- /* target had a different date, so import date should now be set */
- /* note: If sensible defaults are not set in the create:
- an empty Timespec caused problems with the update - fix */
- tc = target_obj->date;
- do_test ((timespec_cmp(&ts, &tc) == 0), "date value check: 1");
- tc = import_obj->date;
- do_test ((timespec_cmp(&tc, &ts) == 0), "date value check: 2");
- do_test ((timespec_cmp(&import_obj->date, &target_obj->date) == 0), "date value check: 3");
-
-}
-
-static void
-test_rule_loop (QofBookMergeData *mergeData, QofBookMergeRule *rule, guint remainder)
-{
- GSList *testing;
- QofParam *eachParam;
- char *importstring;
- char *targetstring;
- /* In this test rule_loop, any lines beginning with do_test() can be removed
- from a working rule_loop routine. It would be wise to still use some of the
- more obvious checks, e.g. that an entity or rule exists before querying the parameters.
-
- Take particular care with MERGE_NEW - targetEnt is always NULL until the Commit.
- Do not attempt to use param_getfcn on targetEnt in the loop called by
- QofBookMergeRuleForeach(rule_loop, MERGE_NEW);
-
- */
- gboolean skip_target;
-
- importstring = NULL;
- targetstring = NULL;
- skip_target = FALSE;
- mergeData->currentRule = rule;
- do_test ((rule != NULL), "loop:#1 Rule is NULL");
- do_test (remainder > 0, "loop:#2 remainder error.");
- do_test ((safe_strcmp(NULL, rule->mergeLabel) != 0), "loop:#3 object label\n");
- do_test ((rule->importEnt != NULL), "loop:#4 empty import entity");
- /* targetEnt is always NULL at this stage if MERGE_NEW is set */
- if (rule->targetEnt == NULL)
- {
- skip_target = TRUE;
- }
- if (!skip_target)
- {
- do_test ((safe_strcmp(rule->importEnt->e_type, rule->targetEnt->e_type) == 0),
- "loop: entity type mismatch");
- }
- do_test ((rule->mergeParam != NULL), "loop: empty parameter list");
- testing = rule->mergeParam;
-
- while (testing != NULL) // start of param loop
- {
- eachParam = testing->data;
- do_test ((eachParam != NULL), "loop:#8 no QofParam data");
- do_test ((eachParam->param_name != NULL), "loop:#9 no parameter name");
- do_test ((eachParam->param_getfcn != NULL), "loop:#10 no get function");
- do_test ((eachParam->param_setfcn != NULL), "loop:#11 no set function");
- /* non-generic - test routines only! */
- if (safe_strcmp(eachParam->param_type, QOF_TYPE_STRING) == 0)
- {
- /* if you use this format, you would need to check the QOF_TYPE and
- configure the get_fcn pointers yourself. This example only works for strings. */
- importstring = g_strdup(eachParam->param_getfcn(rule->importEnt, eachParam));
- do_test ((importstring != NULL), "loop:#12 direct get_fcn import");
- do_test ((safe_strcmp(importstring, "test") == 0), "loop:#13 direct import comparison");
- if (!skip_target)
- {
- targetstring = eachParam->param_getfcn(rule->targetEnt, eachParam);
- do_test ((targetstring != NULL), "loop:#14 direct get_fcn target");
- do_test ((safe_strcmp(targetstring, "testing") == 0), "loop:#15 direct target comparison");
- }
- }
- /* param_as_string does the conversion for display purposes only */
- /* do NOT use as_string for calculations or set_fcn */
- importstring = qof_book_merge_param_as_string(eachParam, rule->importEnt);
- do_test ((importstring != NULL), "loop:#16 import param_as_string is null");
- /* printf("importstring %s\t%s Type\n", importstring, eachParam->param_type);*/
- if (!skip_target)
- {
- targetstring = qof_book_merge_param_as_string(eachParam, rule->targetEnt);
- do_test ((targetstring != NULL), "loop:#17 target param_as_string is null");
- /* printf("targetstring %s\t%s Type\n", targetstring, eachParam->param_type);*/
- }
- /* add your own code for user involvement here. */
- /* either store the importstring and targetstring values and display separately,
- perhaps in alphabetical/object_type/priority order, or, obtain user input as each
- string is available. */
-
- testing = g_slist_next(testing);
- } // end param loop
- /* set each rule dependent on the user involvement response above. */
- /* test routine just sets all MERGE_REPORT to MERGE_UPDATE */
- mergeData = qof_book_merge_update_result(mergeData, MERGE_UPDATE);
- do_test ((rule->mergeResult != MERGE_REPORT), "update result fail");
-}
-
-int
-main (int argc, char **argv)
-{
- qof_init();
- myobjRegister();
- test_merge();
- print_test_results();
- qof_close();
- return get_rv();
-}
Modified: gnucash/trunk/src/libqof/CMakeLists.txt
===================================================================
--- gnucash/trunk/src/libqof/CMakeLists.txt 2011-04-02 19:59:06 UTC (rev 20513)
+++ gnucash/trunk/src/libqof/CMakeLists.txt 2011-04-02 19:59:20 UTC (rev 20514)
@@ -30,7 +30,6 @@
qof/qofreference.c
qof/qofutil.c
qof/qofsession.c
- qof/qofbookmerge.c
)
IF (WIN32)
SET (libgnc_qof_SOURCES ${libgnc_qof_SOURCES}
@@ -72,7 +71,6 @@
qof/qofreference-p.h
qof/qofsession.h
qof/qofutil.h
- qof/qofbookmerge.h
qof/qof-gobject.h
)
Modified: gnucash/trunk/src/libqof/qof/Makefile.am
===================================================================
--- gnucash/trunk/src/libqof/qof/Makefile.am 2011-04-02 19:59:06 UTC (rev 20513)
+++ gnucash/trunk/src/libqof/qof/Makefile.am 2011-04-02 19:59:20 UTC (rev 20514)
@@ -33,8 +33,7 @@
qofquerycore.c \
qofreference.c \
qofutil.c \
- qofsession.c \
- qofbookmerge.c
+ qofsession.c
qofincludedir = ${pkgincludedir}
@@ -65,7 +64,6 @@
qofquerycore.h \
qofsession.h \
qofutil.h \
- qofbookmerge.h \
qof-gobject.h
noinst_HEADERS = \
Modified: gnucash/trunk/src/libqof/qof/qof.h
===================================================================
--- gnucash/trunk/src/libqof/qof/qof.h 2011-04-02 19:59:06 UTC (rev 20513)
+++ gnucash/trunk/src/libqof/qof/qof.h 2011-04-02 19:59:20 UTC (rev 20514)
@@ -93,6 +93,5 @@
#include "qofquerycore.h"
#include "qofsession.h"
#include "qofchoice.h"
-#include "qofbookmerge.h"
#endif /* QOF_H_ */
Deleted: gnucash/trunk/src/libqof/qof/qofbookmerge.c
===================================================================
--- gnucash/trunk/src/libqof/qof/qofbookmerge.c 2011-04-02 19:59:06 UTC (rev 20513)
+++ gnucash/trunk/src/libqof/qof/qofbookmerge.c 2011-04-02 19:59:20 UTC (rev 20514)
@@ -1,1325 +0,0 @@
-/*********************************************************************
- * QofBookMerge.c -- api for QoFBook merge with collision handling *
- * Copyright (C) 2004-2005 Neil Williams <linux at codehelp.co.uk> *
- * *
- * This program is free software; you can redistribute it and/or *
- * modify it under the terms of the GNU General Public License as *
- * published by the Free Software Foundation; either version 2 of *
- * the License, or (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, contact: *
- * *
- * Free Software Foundation Voice: +1-617-542-5942 *
- * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
- * Boston, MA 02110-1301, USA gnu at gnu.org *
- * *
- ********************************************************************/
-
-#include "config.h"
-#include <glib.h>
-#include "qof.h"
-
-static QofLogModule log_module = QOF_MOD_MERGE;
-
-/* private rule iteration struct */
-struct QofBookMergeRuleIterate
-{
- QofBookMergeRuleForeachCB fcn;
- QofBookMergeData *data;
- QofBookMergeRule *rule;
- GList *ruleList;
- guint remainder;
-};
-
-/* Make string type parameters 3 times more
- important in the match than default types.
- i.e. even if two other parameters differ,
- a string match will still provide a better target
- than when other types match and the string does not.
-*/
-#define DEFAULT_MERGE_WEIGHT 1
-#define QOF_STRING_WEIGHT 3
-#define QOF_DATE_STRING_LENGTH MAX_DATE_LENGTH
-
-static QofBookMergeRule*
-qof_book_merge_update_rule(QofBookMergeRule *currentRule, gboolean match, gint weight)
-{
- gboolean absolute;
-
- absolute = currentRule->mergeAbsolute;
- if (absolute && match && currentRule->mergeResult == MERGE_UNDEF)
- {
- currentRule->mergeResult = MERGE_ABSOLUTE;
- }
- if (absolute && !match)
- {
- currentRule->mergeResult = MERGE_UPDATE;
- }
- if (!absolute && match && currentRule->mergeResult == MERGE_UNDEF)
- {
- currentRule->mergeResult = MERGE_DUPLICATE;
- }
- if (!absolute && !match)
- {
- currentRule->difference += weight;
- if (currentRule->mergeResult == MERGE_DUPLICATE)
- {
- currentRule->mergeResult = MERGE_REPORT;
- }
- }
- return currentRule;
-}
-
-struct collect_list_s
-{
- GSList *linkedEntList;
-};
-
-static void
-collect_reference_cb (QofInstance *ent, gpointer user_data)
-{
- struct collect_list_s *s;
-
- s = (struct collect_list_s*)user_data;
- if (!ent || !s)
- {
- return;
- }
- s->linkedEntList = g_slist_prepend(s->linkedEntList, ent);
-}
-
-static int
-qof_book_merge_compare(QofBookMergeData *mergeData )
-{
- QofBookMergeRule *currentRule;
- QofCollection *mergeColl, *targetColl;
- gchar *stringImport, *stringTarget;
- QofInstance *mergeEnt, *targetEnt, *referenceEnt;
- const GncGUID *guidImport, *guidTarget;
- QofParam *qtparam;
- KvpFrame *kvpImport, *kvpTarget;
- QofIdType mergeParamName;
- QofType mergeType;
- GSList *paramList;
- gboolean absolute, mergeError, knowntype, mergeMatch, booleanImport, booleanTarget,
- (*boolean_getter) (QofInstance*, QofParam*);
- Timespec tsImport, tsTarget, (*date_getter) (QofInstance*, QofParam*);
- gnc_numeric numericImport, numericTarget, (*numeric_getter) (QofInstance*, QofParam*);
- double doubleImport, doubleTarget, (*double_getter) (QofInstance*, QofParam*);
- gint32 i32Import, i32Target, (*int32_getter) (QofInstance*, QofParam*);
- gint64 i64Import, i64Target, (*int64_getter) (QofInstance*, QofParam*);
- gchar charImport, charTarget, (*char_getter) (QofInstance*, QofParam*);
-
- ENTER (" ");
-
- g_return_val_if_fail((mergeData != NULL), -1);
- currentRule = mergeData->currentRule;
- g_return_val_if_fail((currentRule != NULL), -1);
- absolute = currentRule->mergeAbsolute;
- mergeEnt = currentRule->importEnt;
- targetEnt = currentRule->targetEnt;
- paramList = currentRule->mergeParam;
- currentRule->difference = 0;
- currentRule->mergeResult = MERGE_UNDEF;
- currentRule->linkedEntList = NULL;
- g_return_val_if_fail((targetEnt) || (mergeEnt) || (paramList), -1);
- kvpImport = kvp_frame_new();
- kvpTarget = kvp_frame_new();
- mergeError = FALSE;
- while (paramList != NULL)
- {
- mergeMatch = FALSE;
- knowntype = FALSE;
- qtparam = paramList->data;
- mergeParamName = qtparam->param_name;
- g_return_val_if_fail(mergeParamName != NULL, -1);
- mergeType = qtparam->param_type;
- if (safe_strcmp(mergeType, QOF_TYPE_STRING) == 0)
- {
- stringImport = qtparam->param_getfcn(mergeEnt, qtparam);
- stringTarget = qtparam->param_getfcn(targetEnt, qtparam);
- /* very strict string matches may need to be relaxed. */
- if (stringImport == NULL)
- {
- stringImport = "";
- }
- if (stringTarget == NULL)
- {
- stringTarget = "";
- }
- if (safe_strcmp(stringImport, stringTarget) == 0)
- {
- mergeMatch = TRUE;
- }
- /* Give special weight to a string match */
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, QOF_STRING_WEIGHT);
- stringImport = stringTarget = NULL;
- knowntype = TRUE;
- }
- if (safe_strcmp(mergeType, QOF_TYPE_DATE) == 0)
- {
- date_getter = (Timespec (*)(QofInstance*, QofParam*))qtparam->param_getfcn;
- tsImport = date_getter(mergeEnt, qtparam);
- tsTarget = date_getter(targetEnt, qtparam);
- if (timespec_cmp(&tsImport, &tsTarget) == 0)
- {
- mergeMatch = TRUE;
- }
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype = TRUE;
- }
- if ((safe_strcmp(mergeType, QOF_TYPE_NUMERIC) == 0) ||
- (safe_strcmp(mergeType, QOF_TYPE_DEBCRED) == 0))
- {
- numeric_getter = (gnc_numeric (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- numericImport = numeric_getter(mergeEnt, qtparam);
- numericTarget = numeric_getter(targetEnt, qtparam);
- if (gnc_numeric_compare (numericImport, numericTarget) == 0)
- {
- mergeMatch = TRUE;
- }
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype = TRUE;
- }
- if (safe_strcmp(mergeType, QOF_TYPE_GUID) == 0)
- {
- guidImport = qtparam->param_getfcn(mergeEnt, qtparam);
- guidTarget = qtparam->param_getfcn(targetEnt, qtparam);
- if (guid_compare(guidImport, guidTarget) == 0)
- {
- mergeMatch = TRUE;
- }
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype = TRUE;
- }
- if (safe_strcmp(mergeType, QOF_TYPE_INT32) == 0)
- {
- int32_getter = (gint32 (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- i32Import = int32_getter(mergeEnt, qtparam);
- i32Target = int32_getter(targetEnt, qtparam);
- if (i32Target == i32Import)
- {
- mergeMatch = TRUE;
- }
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype = TRUE;
- }
- if (safe_strcmp(mergeType, QOF_TYPE_INT64) == 0)
- {
- int64_getter = (gint64 (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- i64Import = int64_getter(mergeEnt, qtparam);
- i64Target = int64_getter(targetEnt, qtparam);
- if (i64Target == i64Import)
- {
- mergeMatch = TRUE;
- }
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype = TRUE;
- }
- if (safe_strcmp(mergeType, QOF_TYPE_DOUBLE) == 0)
- {
- double_getter = (double (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- doubleImport = double_getter(mergeEnt, qtparam);
- doubleTarget = double_getter(mergeEnt, qtparam);
- if (doubleImport == doubleTarget)
- {
- mergeMatch = TRUE;
- }
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype = TRUE;
- }
- if (safe_strcmp(mergeType, QOF_TYPE_BOOLEAN) == 0)
- {
- boolean_getter = (gboolean (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- booleanImport = boolean_getter(mergeEnt, qtparam);
- booleanTarget = boolean_getter(targetEnt, qtparam);
- if (booleanImport != FALSE && booleanImport != TRUE)
- {
- booleanImport = FALSE;
- }
- if (booleanTarget != FALSE && booleanTarget != TRUE)
- {
- booleanTarget = FALSE;
- }
- if (booleanImport == booleanTarget)
- {
- mergeMatch = TRUE;
- }
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype = TRUE;
- }
- if (safe_strcmp(mergeType, QOF_TYPE_KVP) == 0)
- {
- kvpImport = kvp_frame_copy(qtparam->param_getfcn(mergeEnt, qtparam));
- kvpTarget = kvp_frame_copy(qtparam->param_getfcn(targetEnt, qtparam));
- if (kvp_frame_compare(kvpImport, kvpTarget) == 0)
- {
- mergeMatch = TRUE;
- }
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype = TRUE;
- }
- if (safe_strcmp(mergeType, QOF_TYPE_CHAR) == 0)
- {
- char_getter = (gchar (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- charImport = char_getter(mergeEnt, qtparam);
- charTarget = char_getter(targetEnt, qtparam);
- if (charImport == charTarget)
- {
- mergeMatch = TRUE;
- }
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype = TRUE;
- }
- /* No object should have QofSetterFunc defined for the book,
- but just to be safe, do nothing. */
- if (safe_strcmp(mergeType, QOF_ID_BOOK) == 0)
- {
- knowntype = TRUE;
- }
- if (safe_strcmp(mergeType, QOF_TYPE_COLLECT) == 0)
- {
- struct collect_list_s s;
- s.linkedEntList = NULL;
- mergeColl = qtparam->param_getfcn(mergeEnt, qtparam);
- targetColl = qtparam->param_getfcn(targetEnt, qtparam);
- s.linkedEntList = g_slist_copy(currentRule->linkedEntList);
- qof_collection_foreach(mergeColl, collect_reference_cb, &s);
- currentRule->linkedEntList = g_slist_copy(s.linkedEntList);
- if (0 == qof_collection_compare(mergeColl, targetColl))
- {
- mergeMatch = TRUE;
- }
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, DEFAULT_MERGE_WEIGHT);
- knowntype = TRUE;
- }
- if (safe_strcmp(mergeType, QOF_TYPE_CHOICE) == 0)
- {
- referenceEnt = qtparam->param_getfcn(mergeEnt, qtparam);
- currentRule->linkedEntList =
- g_slist_prepend(currentRule->linkedEntList, referenceEnt);
- if (referenceEnt == qtparam->param_getfcn(targetEnt, qtparam))
- {
- mergeMatch = TRUE;
- }
- knowntype = TRUE;
- }
- if (knowntype == FALSE)
- {
- referenceEnt = qtparam->param_getfcn(mergeEnt, qtparam);
-
- // XXX gncOwner is na object that could be returned, but does not have QofInstance
- if (safe_strcmp(qtparam->param_type, "gncOwner") == 0)
- referenceEnt = NULL;
-
- if ((referenceEnt != NULL)
- && (safe_strcmp(referenceEnt->e_type, mergeType) == 0))
- {
- currentRule->linkedEntList =
- g_slist_prepend(currentRule->linkedEntList, referenceEnt);
- if (referenceEnt == qtparam->param_getfcn(targetEnt, qtparam))
- {
- mergeMatch = TRUE;
- }
- currentRule = qof_book_merge_update_rule(currentRule,
- mergeMatch, DEFAULT_MERGE_WEIGHT);
- }
- }
- paramList = g_slist_next(paramList);
- }
- mergeData->currentRule = currentRule;
- g_free(kvpImport);
- g_free(kvpTarget);
-
- LEAVE (" ");
- return 0;
-}
-
-static void
-qof_book_merge_commit_foreach_cb(gpointer rule, gpointer arg)
-{
- struct QofBookMergeRuleIterate *iter;
-
- g_return_if_fail(arg != NULL);
- iter = (struct QofBookMergeRuleIterate*)arg;
- g_return_if_fail(iter->data != NULL);
- iter->fcn (iter->data, (QofBookMergeRule*)rule, iter->remainder);
- iter->remainder--;
-}
-
-static void
-qof_book_merge_commit_foreach (QofBookMergeRuleForeachCB cb,
- QofBookMergeResult mergeResult,
- QofBookMergeData *mergeData)
-{
- struct QofBookMergeRuleIterate iter;
- QofBookMergeRule *currentRule;
- GList *subList, *node;
-
- g_return_if_fail(cb != NULL);
- g_return_if_fail(mergeData != NULL);
- currentRule = mergeData->currentRule;
- g_return_if_fail(currentRule != NULL);
- g_return_if_fail(mergeResult > 0);
- g_return_if_fail((mergeResult != MERGE_INVALID) || (mergeResult != MERGE_UNDEF) || (mergeResult != MERGE_REPORT));
-
- iter.fcn = cb;
- subList = NULL;
- iter.ruleList = NULL;
- for (node = mergeData->mergeList; node != NULL; node = node->next)
- {
- currentRule = node->data;
- if (currentRule->mergeResult == mergeResult)
- {
- subList = g_list_prepend(subList, currentRule);
- }
- }
- iter.remainder = g_list_length(subList);
- iter.data = mergeData;
- g_list_foreach (subList, qof_book_merge_commit_foreach_cb, &iter);
-}
-
-/* build the table of target comparisons
-
-This can get confusing, so bear with me. (!)
-
-Whilst iterating through the entities in the mergeBook, qof_book_mergeForeach assigns
-a targetEnt to each mergeEnt (until it runs out of targetEnt or mergeEnt). Each match
-is made against the one targetEnt that best matches the mergeEnt. Fine so far.
-
-Any mergeEnt is only ever assigned a targetEnt if the calculated difference between
-the two is less than the difference between that targetEnt and any previous mergeEnt
-match.
-
-The next mergeEnt may be a much better match for that targetEnt and the target_table
-is designed to solve the issues that result from this conflict. The previous match
-must be re-assigned because if two mergeEnt's are matched with only one targetEnt,
-data loss \b WILL follow. Equally, the current mergeEnt must replace the previous
-one as it is a better match. qof_instance_rating holds the details required to identify
-the correct mergeEnt to be re-assigned and these mergeEnt entities are therefore
-orphaned - to be re-matched later.
-
-Meanwhile, the current mergeEnt is entered into target_table with it's difference and
-rule data, in case an even better match is found later in the mergeBook.
-
-Finally, each mergeEnt in the orphan_list is now put through the comparison again.
-
-*/
-static gboolean
-qof_book_merge_rule_cmp(gconstpointer a, gconstpointer b)
-{
- QofBookMergeRule *ra = (QofBookMergeRule *) a;
- QofBookMergeRule *rb = (QofBookMergeRule *) b;
- if (ra->difference == rb->difference)
- {
- return TRUE;
- }
- else return FALSE;
-}
-
-static void
-qof_book_merge_orphan_check(double difference, QofBookMergeRule *mergeRule,
- QofBookMergeData *mergeData)
-{
- /* Called when difference is lower than previous
- Lookup target to find previous match
- and re-assign mergeEnt to orphan_list */
- QofBookMergeRule *rule;
-
- g_return_if_fail(mergeRule != NULL);
- g_return_if_fail(mergeData != NULL);
- if (g_hash_table_size(mergeData->target_table) == 0)
- {
- return;
- }
- rule = (QofBookMergeRule*)g_hash_table_lookup(mergeData->target_table,
- mergeRule->targetEnt);
- /* If NULL, no match was found. */
- if (rule == NULL)
- {
- return;
- }
- /* Only orphan if this is a better match than already exists. */
- if (difference >= rule->difference)
- {
- return;
- }
- rule->targetEnt = NULL;
- rule->mergeResult = MERGE_UNDEF;
- mergeData->orphan_list = g_slist_append(mergeData->orphan_list, rule);
-}
-
-static void
-qof_book_merge_match_orphans(QofBookMergeData *mergeData)
-{
- GSList *orphans, *targets;
- QofBookMergeRule *rule, *currentRule;
- QofInstance *best_matchEnt;
- double difference;
-
- ENTER (" ");
-
- g_return_if_fail(mergeData != NULL);
- currentRule = mergeData->currentRule;
- g_return_if_fail(currentRule != NULL);
- /* This routine does NOT copy the orphan list, it
- is used recursively until empty. */
- orphans = mergeData->orphan_list;
- targets = g_slist_copy(mergeData->targetList);
- while (orphans != NULL)
- {
- rule = orphans->data;
- g_return_if_fail(rule != NULL);
- difference = g_slist_length(mergeData->mergeObjectParams);
- if (rule->targetEnt == NULL)
- {
- rule->mergeResult = MERGE_NEW;
- rule->difference = 0;
- mergeData->mergeList = g_list_prepend(mergeData->mergeList, rule);
- orphans = g_slist_next(orphans);
- continue;
- }
- mergeData->currentRule = rule;
- g_return_if_fail(qof_book_merge_compare(mergeData) != -1);
- if (difference > mergeData->currentRule->difference)
- {
- best_matchEnt = currentRule->targetEnt;
- difference = currentRule->difference;
- rule = currentRule;
- mergeData->mergeList = g_list_prepend(mergeData->mergeList, rule);
- qof_book_merge_orphan_check(difference, rule, mergeData);
- }
- orphans = g_slist_next(orphans);
- }
- g_slist_free(mergeData->orphan_list);
- g_slist_free(targets);
-
- LEAVE (" ");
-}
-
-static void
-qof_book_merge_foreach_target (QofInstance* targetEnt, gpointer user_data)
-{
- QofBookMergeData *mergeData;
-
- g_return_if_fail(user_data != NULL);
- mergeData = (QofBookMergeData*)user_data;
- g_return_if_fail(targetEnt != NULL);
- mergeData->targetList = g_slist_prepend(mergeData->targetList, targetEnt);
-}
-
-static void
-qof_book_merge_foreach_type_target ( QofObject* merge_obj, gpointer user_data)
-{
- QofBookMergeData *mergeData;
- QofBookMergeRule *currentRule;
-
- g_return_if_fail(user_data != NULL);
- mergeData = (QofBookMergeData*)user_data;
- currentRule = mergeData->currentRule;
- g_return_if_fail(currentRule != NULL);
- g_return_if_fail(merge_obj != NULL);
- if (safe_strcmp(merge_obj->e_type, currentRule->importEnt->e_type) == 0)
- {
- qof_object_foreach(currentRule->importEnt->e_type, mergeData->targetBook,
- qof_book_merge_foreach_target, user_data);
- }
-}
-
-static void
-qof_book_merge_foreach ( QofInstance* mergeEnt, gpointer user_data)
-{
- QofBookMergeRule *mergeRule, *currentRule;
- QofBookMergeData *mergeData;
- QofInstance *targetEnt, *best_matchEnt;
- GncGUID *g;
- double difference;
- GSList *c;
-
- ENTER (" ");
-
- g_return_if_fail(user_data != NULL);
- mergeData = (QofBookMergeData*)user_data;
- g_return_if_fail(mergeEnt != NULL);
- currentRule = mergeData->currentRule;
- g_return_if_fail(currentRule != NULL);
- g = guid_copy(qof_instance_get_guid(mergeEnt));
- mergeRule = g_new0(QofBookMergeRule, 1);
- mergeRule->importEnt = mergeEnt;
- mergeRule->difference = difference = 0;
- mergeRule->mergeAbsolute = FALSE;
- mergeRule->mergeResult = MERGE_UNDEF;
- mergeRule->updated = FALSE;
- mergeRule->mergeType = mergeEnt->e_type;
- mergeRule->mergeLabel = qof_object_get_type_label(mergeEnt->e_type);
- mergeRule->mergeParam = g_slist_copy(mergeData->mergeObjectParams);
- mergeRule->linkedEntList = NULL;
- mergeData->currentRule = mergeRule;
- targetEnt = best_matchEnt = NULL;
- targetEnt = qof_collection_lookup_entity (
- qof_book_get_collection (mergeData->targetBook, mergeEnt->e_type), g);
- if ( targetEnt != NULL)
- {
- mergeRule->mergeAbsolute = TRUE;
- mergeRule->targetEnt = targetEnt;
- g_return_if_fail(qof_book_merge_compare(mergeData) != -1);
- mergeRule->linkedEntList = g_slist_copy(currentRule->linkedEntList);
- mergeData->mergeList = g_list_prepend(mergeData->mergeList, mergeRule);
- return;
- }
- /* no absolute match exists */
- g_slist_free(mergeData->targetList);
- mergeData->targetList = NULL;
- qof_object_foreach_type(qof_book_merge_foreach_type_target, mergeData);
- if (g_slist_length(mergeData->targetList) == 0)
- {
- mergeRule->mergeResult = MERGE_NEW;
- }
- difference = g_slist_length(mergeRule->mergeParam);
- c = g_slist_copy(mergeData->targetList);
- while (c != NULL)
- {
- mergeRule->targetEnt = c->data;
- currentRule = mergeRule;
- /* compare two entities and sum the differences */
- g_return_if_fail(qof_book_merge_compare(mergeData) != -1);
- if (mergeRule->difference == 0)
- {
- /* check if this is a better match than one already assigned */
- best_matchEnt = mergeRule->targetEnt;
- mergeRule->mergeResult = MERGE_DUPLICATE;
- difference = 0;
- mergeRule->linkedEntList = g_slist_copy(currentRule->linkedEntList);
- g_slist_free(c);
- guid_free(g);
- /* exact match, return */
- return;
- }
- if (difference > mergeRule->difference)
- {
- /* The chosen targetEnt determines the parenting of any child object */
- /* check if this is a better match than one already assigned */
- best_matchEnt = mergeRule->targetEnt;
- difference = mergeRule->difference;
- /* Use match to lookup the previous entity that matched this targetEnt (if any)
- and remove targetEnt from the rule for that mergeEnt.
- Add the previous mergeEnt to orphan_list.
- */
- qof_book_merge_orphan_check(difference, mergeRule, mergeData);
- }
- c = g_slist_next(c);
- }
- g_slist_free(c);
- if (best_matchEnt != NULL )
- {
- mergeRule->targetEnt = best_matchEnt;
- mergeRule->difference = difference;
- /* Set this entity in the target_table in case a better match can be made
- with the next mergeEnt. */
- g_hash_table_insert(mergeData->target_table, mergeRule->targetEnt, mergeRule);
- /* compare again with the best partial match */
- g_return_if_fail(qof_book_merge_compare(mergeData) != -1);
- mergeRule->linkedEntList = g_slist_copy(currentRule->linkedEntList);
- }
- else
- {
- mergeRule->targetEnt = NULL;
- mergeRule->difference = 0;
- mergeRule->mergeResult = MERGE_NEW;
- mergeRule->linkedEntList = g_slist_copy(currentRule->linkedEntList);
- }
- mergeData->mergeList = g_list_prepend(mergeData->mergeList, mergeRule);
- guid_free(g);
- /* return to qof_book_merge_init */
-
- LEAVE (" ");
-}
-
-static void
-qof_book_merge_foreach_param( QofParam* param, gpointer user_data)
-{
- QofBookMergeData *mergeData;
-
- g_return_if_fail(user_data != NULL);
- mergeData = (QofBookMergeData*)user_data;
- g_return_if_fail(param != NULL);
- if ((param->param_getfcn != NULL) && (param->param_setfcn != NULL))
- {
- mergeData->mergeObjectParams = g_slist_append(mergeData->mergeObjectParams, param);
- }
-}
-
-static void
-qof_book_merge_foreach_type ( QofObject* merge_obj, gpointer user_data)
-{
- QofBookMergeData *mergeData;
-
- g_return_if_fail(user_data != NULL);
- mergeData = (QofBookMergeData*)user_data;
- g_return_if_fail((merge_obj != NULL));
- /* Skip unsupported objects */
- if ((merge_obj->create == NULL) || (merge_obj->foreach == NULL))
- {
- DEBUG (" merge_obj QOF support failed %s", merge_obj->e_type);
- return;
- }
- if (mergeData->mergeObjectParams != NULL) g_slist_free(mergeData->mergeObjectParams);
- mergeData->mergeObjectParams = NULL;
- qof_class_param_foreach(merge_obj->e_type, qof_book_merge_foreach_param , mergeData);
- qof_object_foreach(merge_obj->e_type, mergeData->mergeBook,
- qof_book_merge_foreach, mergeData);
-}
-
-static void
-qof_book_merge_rule_cb(gpointer rule, gpointer arg)
-{
- struct QofBookMergeRuleIterate *iter;
- QofBookMergeData *mergeData;
-
- g_return_if_fail(arg != NULL);
- iter = (struct QofBookMergeRuleIterate*)arg;
- mergeData = iter->data;
- g_return_if_fail(mergeData != NULL);
- g_return_if_fail(mergeData->abort == FALSE);
- iter->fcn (mergeData, (QofBookMergeRule*)rule, iter->remainder);
- iter->data = mergeData;
- iter->remainder--;
-}
-
-
-/**
- * Creates an object when the MergeResult is MERGE_NEW. Called for each MergeRule.
- */
-static void
-qof_book_merge_commit_rule_create_objects(QofBookMergeData *mergeData,
- QofBookMergeRule *rule,
- guint remainder)
-{
- QofInstance *inst;
-
- g_return_if_fail(rule != NULL);
- g_return_if_fail(mergeData != NULL);
- g_return_if_fail(mergeData->targetBook != NULL);
- g_return_if_fail(rule->mergeResult == MERGE_NEW);
-
- /* The new object takes the GncGUID from the import to retain an absolute match */
- inst = qof_object_new_instance(rule->importEnt->e_type, mergeData->targetBook);
- g_return_if_fail(inst != NULL);
- rule->targetEnt = inst;
- qof_instance_copy_guid(rule->targetEnt, rule->importEnt);
-}
-
-
-/**
- * Returns the corresponding target entity to the given importEnt
- */
-static QofInstance*
-qof_book_merge_map_entity(const QofBookMergeData *mergeData, const QofInstance* importEnt)
-{
- QofBookMergeRule *currentRule;
- GList *node;
-
- for (node = mergeData->mergeList; node != NULL; node = node->next)
- {
- currentRule = node->data;
- if (currentRule->importEnt == importEnt)
- {
- return currentRule->targetEnt;
- }
- }
- PINFO ("qof_book_merge_map_entity: Import Entity not found");
- return NULL;
-}
-
-typedef struct
-{
- QofBookMergeData *mergeData;
- QofCollection *mapped_coll;
-} QofBookMergeMapCollectionIterate;
-
-
-/**
- * Map all entities given in importEnt and add them into the mapped_coll
- */
-static void
-qof_book_merge_map_collection_cb(QofInstance* importEnt, gpointer user_data)
-{
- QofBookMergeMapCollectionIterate *mapped_coll_iter;
- QofInstance *targetEnt;
-
- mapped_coll_iter = (QofBookMergeMapCollectionIterate*)user_data;
- targetEnt = qof_book_merge_map_entity(mapped_coll_iter->mergeData, importEnt);
- qof_collection_add_entity(mapped_coll_iter->mapped_coll, targetEnt);
-}
-
-
-static void
-qof_book_merge_commit_rule_loop(QofBookMergeData *mergeData,
- QofBookMergeRule *rule,
- guint remainder)
-{
- gboolean registered_type;
- QofInstance *referenceEnt;
- /* cm_ prefix used for variables that hold the data to commit */
- QofCollection *cm_coll, *mapped_coll;
- QofBookMergeMapCollectionIterate mapped_coll_iter;
- QofParam *cm_param;
- gchar *cm_string;
- const GncGUID *cm_guid;
- KvpFrame *cm_kvp;
- /* function pointers and variables for parameter getters that don't use pointers normally */
- gnc_numeric cm_numeric, (*numeric_getter) (QofInstance*, QofParam*);
- double cm_double, (*double_getter) (QofInstance*, QofParam*);
- gboolean cm_boolean, (*boolean_getter) (QofInstance*, QofParam*);
- gint32 cm_i32, (*int32_getter) (QofInstance*, QofParam*);
- gint64 cm_i64, (*int64_getter) (QofInstance*, QofParam*);
- Timespec cm_date, (*date_getter) (QofInstance*, QofParam*);
- gchar cm_char, (*char_getter) (QofInstance*, QofParam*);
- /* function pointers to the parameter setters */
- void (*string_setter) (QofInstance*, const gchar*);
- void (*date_setter) (QofInstance*, Timespec);
- void (*numeric_setter) (QofInstance*, gnc_numeric);
- void (*guid_setter) (QofInstance*, const GncGUID*);
- void (*double_setter) (QofInstance*, double);
- void (*boolean_setter) (QofInstance*, gboolean);
- void (*i32_setter) (QofInstance*, gint32);
- void (*i64_setter) (QofInstance*, gint64);
- void (*char_setter) (QofInstance*, gchar);
- void (*kvp_frame_setter) (QofInstance*, KvpFrame*);
- void (*reference_setter) (QofInstance*, QofInstance*);
- void (*collection_setter)(QofInstance*, QofCollection*);
-
- g_return_if_fail(rule != NULL);
- g_return_if_fail(mergeData != NULL);
- g_return_if_fail(mergeData->targetBook != NULL);
- g_return_if_fail(rule->importEnt && rule->targetEnt);
- g_return_if_fail((rule->mergeResult != MERGE_NEW) || (rule->mergeResult != MERGE_UPDATE));
-
- DEBUG ("qof_book_merge_commit_rule_loop rule: type: %s, result: %s, importEnt Type: %s, guid: %s",
- rule->mergeType, rule->mergeResult == MERGE_NEW ? "New" : "Update",
- rule->importEnt->e_type,
- guid_to_string(qof_instance_get_guid(rule->importEnt)));
- DEBUG ("qof_book_merge_commit_rule_loop rule (cont.): targetEnt Type: %s, guid: %s",
- rule->targetEnt->e_type,
- guid_to_string(qof_instance_get_guid(rule->targetEnt)));
-
- /* currentRule->targetEnt is now set,
- 1. by an absolute GncGUID match or
- 2. by best_matchEnt and difference or
- 3. by MERGE_NEW.
- */
- while (rule->mergeParam != NULL)
- {
- registered_type = FALSE;
- g_return_if_fail(rule->mergeParam->data);
- cm_param = rule->mergeParam->data;
- rule->mergeType = cm_param->param_type;
-
- DEBUG ("qof_book_merge_commit_rule_loop param: Merge Type: %s, Param Name: %s",
- rule->mergeType, cm_param->param_name);
-
- if (safe_strcmp(rule->mergeType, QOF_TYPE_STRING) == 0)
- {
- cm_string = cm_param->param_getfcn(rule->importEnt, cm_param);
- string_setter = (void(*)(QofInstance*, const gchar*))cm_param->param_setfcn;
- if (string_setter != NULL)
- {
- string_setter(rule->targetEnt, cm_string);
- }
- registered_type = TRUE;
- }
- if (safe_strcmp(rule->mergeType, QOF_TYPE_DATE) == 0)
- {
- date_getter = (Timespec (*)(QofInstance*, QofParam*))cm_param->param_getfcn;
- cm_date = date_getter(rule->importEnt, cm_param);
- date_setter = (void(*)(QofInstance*, Timespec))cm_param->param_setfcn;
- if (date_setter != NULL)
- {
- date_setter(rule->targetEnt, cm_date);
- }
- registered_type = TRUE;
- }
- if ((safe_strcmp(rule->mergeType, QOF_TYPE_NUMERIC) == 0) ||
- (safe_strcmp(rule->mergeType, QOF_TYPE_DEBCRED) == 0))
- {
- numeric_getter = (gnc_numeric (*)(QofInstance*, QofParam*))cm_param->param_getfcn;
- cm_numeric = numeric_getter(rule->importEnt, cm_param);
- numeric_setter = (void(*)(QofInstance*, gnc_numeric))cm_param->param_setfcn;
- if (numeric_setter != NULL)
- {
- numeric_setter(rule->targetEnt, cm_numeric);
- }
- registered_type = TRUE;
- }
- if (safe_strcmp(rule->mergeType, QOF_TYPE_GUID) == 0)
- {
- cm_guid = cm_param->param_getfcn(rule->importEnt, cm_param);
- guid_setter = (void(*)(QofInstance*, const GncGUID*))cm_param->param_setfcn;
- if (guid_setter != NULL)
- {
- guid_setter(rule->targetEnt, cm_guid);
- }
- registered_type = TRUE;
- }
- if (safe_strcmp(rule->mergeType, QOF_TYPE_INT32) == 0)
- {
- int32_getter = (gint32 (*)(QofInstance*, QofParam*)) cm_param->param_getfcn;
- cm_i32 = int32_getter(rule->importEnt, cm_param);
- i32_setter = (void(*)(QofInstance*, gint32))cm_param->param_setfcn;
- if (i32_setter != NULL)
- {
- i32_setter(rule->targetEnt, cm_i32);
- }
- registered_type = TRUE;
- }
- if (safe_strcmp(rule->mergeType, QOF_TYPE_INT64) == 0)
- {
- int64_getter = (gint64 (*)(QofInstance*, QofParam*)) cm_param->param_getfcn;
- cm_i64 = int64_getter(rule->importEnt, cm_param);
- i64_setter = (void(*)(QofInstance*, gint64))cm_param->param_setfcn;
- if (i64_setter != NULL)
- {
- i64_setter(rule->targetEnt, cm_i64);
- }
- registered_type = TRUE;
- }
- if (safe_strcmp(rule->mergeType, QOF_TYPE_DOUBLE) == 0)
- {
- double_getter = (double (*)(QofInstance*, QofParam*)) cm_param->param_getfcn;
- cm_double = double_getter(rule->importEnt, cm_param);
- double_setter = (void(*)(QofInstance*, double))cm_param->param_setfcn;
- if (double_setter != NULL)
- {
- double_setter(rule->targetEnt, cm_double);
- }
- registered_type = TRUE;
- }
- if (safe_strcmp(rule->mergeType, QOF_TYPE_BOOLEAN) == 0)
- {
- boolean_getter = (gboolean (*)(QofInstance*, QofParam*)) cm_param->param_getfcn;
- cm_boolean = boolean_getter(rule->importEnt, cm_param);
- boolean_setter = (void(*)(QofInstance*, gboolean))cm_param->param_setfcn;
- if (boolean_setter != NULL)
- {
- boolean_setter(rule->targetEnt, cm_boolean);
- }
- registered_type = TRUE;
- }
- if (safe_strcmp(rule->mergeType, QOF_TYPE_KVP) == 0)
- {
- cm_kvp = kvp_frame_copy(cm_param->param_getfcn(rule->importEnt, cm_param));
- kvp_frame_setter = (void(*)(QofInstance*, KvpFrame*))cm_param->param_setfcn;
- if (kvp_frame_setter != NULL)
- {
- kvp_frame_setter(rule->targetEnt, cm_kvp);
- }
- registered_type = TRUE;
- }
- if (safe_strcmp(rule->mergeType, QOF_TYPE_CHAR) == 0)
- {
- char_getter = (gchar (*)(QofInstance*, QofParam*)) cm_param->param_getfcn;
- cm_char = char_getter(rule->importEnt, cm_param);
- char_setter = (void(*)(QofInstance*, gchar))cm_param->param_setfcn;
- if (char_setter != NULL)
- {
- char_setter(rule->targetEnt, cm_char);
- }
- registered_type = TRUE;
- }
- if (safe_strcmp(rule->mergeType, QOF_TYPE_COLLECT) == 0)
- {
- cm_coll = cm_param->param_getfcn(rule->importEnt, cm_param);
-
- /* Created mapped collection */
- mapped_coll = qof_collection_new(qof_collection_get_type(cm_coll));
- mapped_coll_iter.mergeData = mergeData;
- mapped_coll_iter.mapped_coll = mapped_coll;
- qof_collection_foreach(cm_coll, qof_book_merge_map_collection_cb, &mapped_coll_iter);
-
- collection_setter = (void(*)(QofInstance*, QofCollection*))cm_param->param_setfcn;
- if (collection_setter != NULL)
- {
- collection_setter(rule->targetEnt, mapped_coll);
- }
- registered_type = TRUE;
- }
- if (safe_strcmp(rule->mergeType, QOF_TYPE_CHOICE) == 0)
- {
- referenceEnt = cm_param->param_getfcn(rule->importEnt, cm_param);
- referenceEnt = qof_book_merge_map_entity(mergeData, referenceEnt);
- reference_setter = (void(*)(QofInstance*, QofInstance*))cm_param->param_setfcn;
- if (reference_setter != NULL)
- {
- reference_setter(rule->targetEnt, referenceEnt);
- }
- registered_type = TRUE;
- }
- if (registered_type == FALSE)
- {
- referenceEnt = cm_param->param_getfcn(rule->importEnt, cm_param);
-
- // XXX gncOwner is an object that could be returned, but does not have QofInstance
- if (safe_strcmp(cm_param->param_type, "gncOwner") == 0)
- referenceEnt = NULL;
-
- referenceEnt = qof_book_merge_map_entity(mergeData, referenceEnt);
-
- if (referenceEnt)
- {
- reference_setter = (void(*)(QofInstance*, QofInstance*))cm_param->param_setfcn;
- if (reference_setter != NULL)
- {
- reference_setter(rule->targetEnt, referenceEnt);
- }
- }
- }
- rule->mergeParam = g_slist_next(rule->mergeParam);
- }
-}
-/* ================================================================ */
-/* API functions. */
-
-QofBookMergeData*
-qof_book_merge_init( QofBook *importBook, QofBook *targetBook)
-{
- QofBookMergeData *mergeData;
- QofBookMergeRule *currentRule;
- GList *node;
-
- ENTER (" ");
-
- g_return_val_if_fail((importBook != NULL) && (targetBook != NULL), NULL);
- mergeData = g_new0(QofBookMergeData, 1);
- mergeData->abort = FALSE;
- mergeData->mergeList = NULL;
- mergeData->targetList = NULL;
- mergeData->mergeBook = importBook;
- mergeData->targetBook = targetBook;
- mergeData->mergeObjectParams = NULL;
- mergeData->orphan_list = NULL;
- mergeData->target_table = g_hash_table_new( g_direct_hash, qof_book_merge_rule_cmp);
- currentRule = g_new0(QofBookMergeRule, 1);
- mergeData->currentRule = currentRule;
- qof_object_foreach_type(qof_book_merge_foreach_type, mergeData);
- g_return_val_if_fail(mergeData->mergeObjectParams, NULL);
- if (mergeData->orphan_list != NULL)
- {
- qof_book_merge_match_orphans(mergeData);
- }
-
- for (node = mergeData->mergeList; node != NULL; node = node->next)
- {
- currentRule = node->data;
- if (currentRule->mergeResult == MERGE_INVALID)
- {
- mergeData->abort = TRUE;
- return(NULL);
- }
- }
-
- LEAVE (" ");
- return mergeData;
-}
-
-void
-qof_book_merge_abort (QofBookMergeData *mergeData)
-{
- QofBookMergeRule *currentRule;
-
- g_return_if_fail(mergeData != NULL);
- while (mergeData->mergeList != NULL)
- {
- currentRule = mergeData->mergeList->data;
- g_slist_free(currentRule->linkedEntList);
- g_slist_free(currentRule->mergeParam);
- g_free(mergeData->mergeList->data);
- if (currentRule)
- {
- g_slist_free(currentRule->linkedEntList);
- g_slist_free(currentRule->mergeParam);
- g_free(currentRule);
- }
- mergeData->mergeList = g_list_next(mergeData->mergeList);
- }
- g_list_free(mergeData->mergeList);
- g_slist_free(mergeData->mergeObjectParams);
- g_slist_free(mergeData->targetList);
- if (mergeData->orphan_list != NULL)
- {
- g_slist_free(mergeData->orphan_list);
- }
- g_hash_table_destroy(mergeData->target_table);
- g_free(mergeData);
-}
-
-/* The QOF_TYPE_DATE output format from
-qof_book_merge_param_as_string has been changed to QSF_XSD_TIME,
-a UTC formatted timestring: 2005-01-01T10:55:23Z
-If you change QOF_UTC_DATE_FORMAT, change
-backend/file/qsf-xml.c : qsf_entity_foreach to
-reformat to QSF_XSD_TIME or the QSF XML will
-FAIL the schema validation and QSF exports will become invalid.
-
-The QOF_TYPE_BOOLEAN is lowercase for the same reason.
-
-\todo deprecate and replace with
-gchar* qof_instance_param_as_string(const QofParam*, QofInstance*);
-and then add
-gchar* qof_class_get_param_as_string(QofIdTypeConst, QofInstance*); ?
-*/
-gchar*
-qof_book_merge_param_as_string(QofParam *qtparam, QofInstance *qtEnt)
-{
- gchar *param_string, param_date[QOF_DATE_STRING_LENGTH];
- gchar param_sa[GUID_ENCODING_LENGTH + 1];
- QofType paramType;
- const GncGUID *param_guid;
- time_t param_t;
- gnc_numeric param_numeric, (*numeric_getter) (QofInstance*, QofParam*);
- Timespec param_ts, (*date_getter) (QofInstance*, QofParam*);
- double param_double, (*double_getter) (QofInstance*, QofParam*);
- gboolean param_boolean, (*boolean_getter) (QofInstance*, QofParam*);
- gint32 param_i32, (*int32_getter) (QofInstance*, QofParam*);
- gint64 param_i64, (*int64_getter) (QofInstance*, QofParam*);
- gchar param_char, (*char_getter) (QofInstance*, QofParam*);
-
- param_string = NULL;
- paramType = qtparam->param_type;
- if (safe_strcmp(paramType, QOF_TYPE_STRING) == 0)
- {
- param_string = g_strdup(qtparam->param_getfcn(qtEnt, qtparam));
- if (param_string == NULL)
- {
- param_string = "";
- }
- return param_string;
- }
- if (safe_strcmp(paramType, QOF_TYPE_DATE) == 0)
- {
- date_getter = (Timespec (*)(QofInstance*, QofParam*))qtparam->param_getfcn;
- param_ts = date_getter(qtEnt, qtparam);
- param_t = timespecToTime_t(param_ts);
- qof_strftime(param_date, QOF_DATE_STRING_LENGTH, QOF_UTC_DATE_FORMAT, gmtime(¶m_t));
- param_string = g_strdup(param_date);
- return param_string;
- }
- if ((safe_strcmp(paramType, QOF_TYPE_NUMERIC) == 0) ||
- (safe_strcmp(paramType, QOF_TYPE_DEBCRED) == 0))
- {
- numeric_getter = (gnc_numeric (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- param_numeric = numeric_getter(qtEnt, qtparam);
- param_string = g_strdup(gnc_numeric_to_string(param_numeric));
- return param_string;
- }
- if (safe_strcmp(paramType, QOF_TYPE_GUID) == 0)
- {
- param_guid = qtparam->param_getfcn(qtEnt, qtparam);
- guid_to_string_buff(param_guid, param_sa);
- param_string = g_strdup(param_sa);
- return param_string;
- }
- if (safe_strcmp(paramType, QOF_TYPE_INT32) == 0)
- {
- int32_getter = (gint32 (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- param_i32 = int32_getter(qtEnt, qtparam);
- param_string = g_strdup_printf("%d", param_i32);
- return param_string;
- }
- if (safe_strcmp(paramType, QOF_TYPE_INT64) == 0)
- {
- int64_getter = (gint64 (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- param_i64 = int64_getter(qtEnt, qtparam);
- param_string = g_strdup_printf("%" G_GINT64_FORMAT, param_i64);
- return param_string;
- }
- if (safe_strcmp(paramType, QOF_TYPE_DOUBLE) == 0)
- {
- double_getter = (double (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- param_double = double_getter(qtEnt, qtparam);
- param_string = g_strdup_printf("%f", param_double);
- return param_string;
- }
- if (safe_strcmp(paramType, QOF_TYPE_BOOLEAN) == 0)
- {
- boolean_getter = (gboolean (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- param_boolean = boolean_getter(qtEnt, qtparam);
- /* Boolean values need to be lowercase for QSF validation. */
- if (param_boolean == TRUE)
- {
- param_string = g_strdup("true");
- }
- else
- {
- param_string = g_strdup("false");
- }
- return param_string;
- }
- /* "kvp" contains repeating values, cannot be a single string for the frame. */
- if (safe_strcmp(paramType, QOF_TYPE_KVP) == 0)
- {
- return param_string;
- }
- if (safe_strcmp(paramType, QOF_TYPE_CHAR) == 0)
- {
- char_getter = (gchar (*)(QofInstance*, QofParam*)) qtparam->param_getfcn;
- param_char = char_getter(qtEnt, qtparam);
- param_string = g_strdup_printf("%c", param_char);
- return param_string;
- }
- return NULL;
-}
-
-QofBookMergeData*
-qof_book_merge_update_result (QofBookMergeData *mergeData,
- QofBookMergeResult tag)
-{
- QofBookMergeRule *resolved;
-
- g_return_val_if_fail((mergeData != NULL), NULL);
- g_return_val_if_fail((tag > 0), NULL);
- g_return_val_if_fail((tag != MERGE_REPORT), NULL);
- resolved = mergeData->currentRule;
- g_return_val_if_fail((resolved != NULL), NULL);
- if ((resolved->mergeAbsolute == TRUE) && (tag == MERGE_DUPLICATE))
- {
- tag = MERGE_ABSOLUTE;
- }
- if ((resolved->mergeAbsolute == TRUE) && (tag == MERGE_NEW))
- {
- tag = MERGE_UPDATE;
- }
- if ((resolved->mergeAbsolute == FALSE) && (tag == MERGE_ABSOLUTE))
- {
- tag = MERGE_DUPLICATE;
- }
- if ((resolved->mergeResult == MERGE_NEW) && (tag == MERGE_UPDATE))
- {
- tag = MERGE_NEW;
- }
- if (resolved->updated == FALSE)
- {
- resolved->mergeResult = tag;
- }
- resolved->updated = TRUE;
- if (tag >= MERGE_INVALID)
- {
- mergeData->abort = TRUE;
- mergeData->currentRule = resolved;
- return NULL;
- }
- mergeData->currentRule = resolved;
- return mergeData;
-}
-
-gint
-qof_book_merge_commit(QofBookMergeData *mergeData )
-{
- QofBookMergeRule *currentRule;
- GList *check, *node;
-
- ENTER (" ");
-
- g_return_val_if_fail(mergeData != NULL, -10);
- g_return_val_if_fail(mergeData->mergeList != NULL, -11);
- g_return_val_if_fail(mergeData->targetBook != NULL, -12);
- if (mergeData->abort == TRUE) return -13;
- check = g_list_copy(mergeData->mergeList);
- g_return_val_if_fail(check != NULL, -14);
- for (node = check; node != NULL; node = node->next)
- {
- currentRule = node->data;
-
- if (currentRule->mergeResult == MERGE_INVALID)
- {
- qof_book_merge_abort(mergeData);
- g_list_free(check);
- return(-2);
- }
- if (currentRule->mergeResult == MERGE_REPORT)
- {
- g_list_free(check);
- return 1;
- }
- }
- g_list_free(check);
- qof_book_merge_commit_foreach(qof_book_merge_commit_rule_create_objects,
- MERGE_NEW, mergeData);
- qof_book_merge_commit_foreach(qof_book_merge_commit_rule_loop,
- MERGE_NEW, mergeData);
- qof_book_merge_commit_foreach(qof_book_merge_commit_rule_loop,
- MERGE_UPDATE, mergeData);
-
- /* Placeholder for QofObject merge_helper_cb - all objects
- and all parameters set */
- while (mergeData->mergeList != NULL)
- {
- currentRule = mergeData->mergeList->data;
- g_slist_free(currentRule->mergeParam);
- g_slist_free(currentRule->linkedEntList);
- mergeData->mergeList = g_list_next(mergeData->mergeList);
- }
- g_list_free(mergeData->mergeList);
- g_slist_free(mergeData->mergeObjectParams);
- g_slist_free(mergeData->targetList);
- if (mergeData->orphan_list != NULL)
- {
- g_slist_free(mergeData->orphan_list);
- }
- g_hash_table_destroy(mergeData->target_table);
- g_free(mergeData);
-
- LEAVE (" ");
- return 0;
-}
-
-void
-qof_book_merge_rule_foreach (QofBookMergeData *mergeData,
- QofBookMergeRuleForeachCB cb,
- QofBookMergeResult mergeResult )
-{
- struct QofBookMergeRuleIterate iter;
- QofBookMergeRule *currentRule;
- GList *matching_rules, *node;
-
- g_return_if_fail(cb != NULL);
- g_return_if_fail(mergeData != NULL);
- currentRule = mergeData->currentRule;
- g_return_if_fail(mergeResult > 0);
- g_return_if_fail(mergeResult != MERGE_INVALID);
- g_return_if_fail(mergeData->abort == FALSE);
- iter.fcn = cb;
- iter.data = mergeData;
- matching_rules = NULL;
- iter.ruleList = NULL;
- for (node = mergeData->mergeList; node != NULL; node = node->next)
- {
- currentRule = node->data;
- if (currentRule->mergeResult == mergeResult)
- {
- matching_rules = g_list_prepend(matching_rules, currentRule);
- }
- }
- iter.remainder = g_list_length(matching_rules);
- g_list_foreach (matching_rules, qof_book_merge_rule_cb, &iter);
- g_list_free(matching_rules);
-}
-
-/* End of file. */
-/* ==================================================================== */
Deleted: gnucash/trunk/src/libqof/qof/qofbookmerge.h
===================================================================
--- gnucash/trunk/src/libqof/qof/qofbookmerge.h 2011-04-02 19:59:06 UTC (rev 20513)
+++ gnucash/trunk/src/libqof/qof/qofbookmerge.h 2011-04-02 19:59:20 UTC (rev 20514)
@@ -1,495 +0,0 @@
-/*********************************************************************
- * qofbookmerge.h -- api for QofBook merge with collision handling *
- * Copyright (C) 2004 Neil Williams <linux at codehelp.co.uk> *
- * *
- * This program is free software; you can redistribute it and/or *
- * modify it under the terms of the GNU General Public License as *
- * published by the Free Software Foundation; either version 2 of *
- * the License, or (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, contact: *
- * *
- * Free Software Foundation Voice: +1-617-542-5942 *
- * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
- * Boston, MA 02110-1301, USA gnu at gnu.org *
- * *
- ********************************************************************/
-
-#ifndef QOFBOOKMERGE_H
-#define QOFBOOKMERGE_H
-
-#define QOF_MOD_MERGE "qof.merge"
-
-/** @addtogroup BookMerge
-
-<b>Collision handling principles.</b>\n
-\n
- -# Always check for a ::GncGUID first and compare. qofbookmerge only accepts
- valid ::QofBook data and therefore ALL objects in the import book will
- include valid GncGUID's.
- -# If the original import data did not contain a GncGUID (e.g. an external
- non-GnuCash source) the GncGUID values will have been created during the
- import and will not match any existing GncGUID's in the target book so objects
- that do not have a GncGUID match cannot be assumed to be ::MERGE_NEW - parameter
- values must be checked.
- -# If import contains data from closed books, store the data from the closed
- books in the current book as active. i.e. re-open the books.
-
-- If a GncGUID match exists, set qof_book_merge_rule::mergeAbsolute to \a TRUE.
- -# If ALL parameters in the import object match the target object with
- the same \a GncGUID,
- set ::qof_book_merge_result to \a MERGE_ABSOLUTE.
- -# If any parameters differ, set ::MERGE_UPDATE.
-- If the import object \a GncGUID does not match an existing object,
-mergeAbsolute is unchanged from the default \a FALSE
-The parameter values of the object are compared to other objects of the same
-type in the target book.
- -# If the same data exists in the target book with a different GncGUID, the object
- is tagged as DUPLICATE.
- -# If the data has changed, the object is tagged as REPORT.
- -# If the data does not match, the object is tagged as NEW
-
-More information is at http://code.neil.williamsleesmill.me.uk/
-
-Each foreach function uses g_return_if_fail checks to protect the target book.
-If any essential data is missing, the loop returns without changing the target
-book. Note that this will not set or return an error value. However, g_return
-is only used for critical errors that arise from programming errors, not for
-invalid import data which should be cleaned up before creating the import
-QofBook.
-
-Only ::qof_book_merge_update_result and ::qof_book_merge_commit return
-any error values to the calling process. ::qof_book_merge_init returns a
-pointer to the ::QofBookMergeData struct - the calling process needs to
-make sure this is non-NULL to know that the Init has been successful.
-
- @{
-*/
-/** @file qofbookmerge.h
- @brief API for merging two \c QofBook structures with collision handling
- @author Copyright (c) 2004-2005 Neil Williams <linux at codehelp.co.uk>
-*/
-
-#include "qofutil.h"
-#include "qofbook.h"
-#include "qofclass.h"
-#include "qofobject.h"
-#include "qofinstance.h"
-#include "qoflog.h"
-
-/** \brief Results of collisions and user resolution.
-
-All rules are initialised as ::MERGE_UNDEF.
-Once the comparison is complete, each object within the import will be
-updated.
-
-::MERGE_ABSOLUTE, ::MERGE_NEW, ::MERGE_DUPLICATE and ::MERGE_UPDATE can be
-reported to the user along with all ::MERGE_REPORT objects for confirmation.
-It may be useful later to allow \a MERGE_ABSOLUTE, \a MERGE_NEW,
-\a MERGE_DUPLICATE and \a MERGE_UPDATE to not be reported, if the user sets a
-preferences option for each result. (Always accept new items: Y/N default NO,
-ignores all MERGE_NEW if set to Y etc.) This option would not require any
-changes to qofbookmerge.
-
-\a MERGE_NEW, \a MERGE_DUPLICATE and \a MERGE_UPDATE are only actioned after
-conflicts are resolved by the user using a dialog and all \a MERGE_REPORT
-objects are re-assigned to one of MERGE_NEW, MERGE_DUPLICATE or MERGE_UPDATE.
-There is no automatic merge, even if no entities are tagged as MERGE_REPORT,
-the calling process must still check for REPORT items using
-::qof_book_merge_rule_foreach and call ::qof_book_merge_commit.
-
-\a MERGE_INVALID data should be rare and allows for user-abort - the imported
-file/source may be corrupted and the prescence of invalid data should raise
-concerns that the rest of the data may be corrupted, damaged or otherwise
-altered. If any entity is tagged as MERGE_INVALID, the merge operation will
-abort and leave the target book completely unchanged.
-
-\a MERGE_ABSOLUTE is only used for a complete match. The import object contains
-the same data in the same parameters with no omissions or amendments. If any
-data is missing, amended or added, the data is labelled \a MERGE_UPDATE.
-
- Every piece of data has a corresponding result. Only when the count of items
- labelled \a MERGE_REPORT is equal to zero are \a MERGE_NEW and \a MERGE_UPDATE
- items added to the existing book.\n \a MERGE_DUPLICATE items are silently
- ignored. Aborting the dialogue/process (by the user or in a program crash) at
- any point before the final commit leaves the existing book completely untouched.
-*/
-typedef enum
-{
- MERGE_UNDEF, /**< default value before comparison is made. */
- MERGE_ABSOLUTE, /**< GncGUID exact match, no new data - \b ignore */
- MERGE_NEW, /**< import object does \b not exist in the target
- book - \b add */
- MERGE_REPORT, /**< import object needs user intervention - \b report */
- MERGE_DUPLICATE, /**< import object with different GncGUID exactly matches
- existing GncGUID - \b ignore */
- MERGE_UPDATE, /**< import object matches an existing entity but includes
- new or modified parameter data - \b update */
- MERGE_INVALID /**< import object didn't match registered object or
- parameter types or user decided to abort - \b abort */
-} QofBookMergeResult;
-
-/** \brief One rule per entity, built into a single GList for the entire merge
-
-All rules are stored in the GList QofBookMergeData::mergeList.
-
-If the ::GncGUID matches it's the always same semantic object,
-regardless of whether other data fields are changed.
-\n
-The boolean value mergeAbsolute defaults to \c FALSE
-
-NOTE 1: if mergeAbsolute == \c TRUE, ::QofBookMergeResult will still be set
-to ::MERGE_UPDATE if parameters within this entity have been modified.
-
-NOTE 2: ::qof_book_merge_param_as_string returns \b string representations of
-the parameter data that is causing a collision. These values must \b NOT be
-used to set the target parameter - the function is provided for display
-purposes only, to make it simple to explain the collision to the user using
-MERGE_REPORT and the dialogue.
-
-The GHashTable targetTable in QofBookMergeRule will probably replace the
-GSList of the
-same name in mergeData.
-
-*/
-
-typedef struct
-{
- /* internal counters and reference variables */
- gboolean mergeAbsolute; /**< Only set if the GncGUID of the import matches
- the target */
- double difference; /**< used to find best match in a book where no
- GncGUID matches */
- gboolean updated; /**< prevent the mergeResult from being
- overwritten. */
- /* rule objects set from or by external calls */
- QofIdType mergeType; /**< type of comparison required for check for
- collision */
- const gchar* mergeLabel; /**< Descriptive label for the object type,
- useful for the user intervention dialogue. */
- GSList *mergeParam; /**< list of usable parameters for the object type */
- GSList *linkedEntList; /**< list of complex data types included in this object.
-
- linkedEntList contains an ::QofInstance reference to any parameter that is not
- one of the core QOF_TYPE data types. This entity must be already
- registered with QOF and the results of the comparison for the linked entity
- will modulate the mergeResult of this object. e.g. if an invoice is the
- same value but for a different customer, the invoice will be set to
- MERGE_REPORT and the customer as MERGE_NEW.
- */
- QofBookMergeResult mergeResult; /**< result of comparison with main ::QofBook */
- QofInstance *importEnt; /**< pointer to the current entity in the import book. */
- QofInstance *targetEnt; /**< pointer to the corresponding entity in the
- target book, if any. */
-} QofBookMergeRule;
-
-
-/** \brief mergeData contains the essential context data for any merge.
-
-Used to dictate what to merge, how to merge it, where to get the new data and
-where to put the amended data.
-
-Combines lists of \a ::QofParam, \a ::QofInstance and \a ::QofBookMergeRule
-into one struct that can be easily passed between callbacks. Also holds the
-pointers to the import and target ::QofBook structures.
-
-- targetList and mergeObjectParams change each time a new object type
-is set for compare.
-- mergeList is the complete list of rules for all objects in the import book.
-
-*/
-typedef struct
-{
- GSList *mergeObjectParams; /**< GSList of ::QofParam details for each
- parameter in the current object. */
- GList *mergeList; /**< GList of all ::QofBookMergeRule rules
- for the merge operation. */
- GSList *targetList; /**< GSList of ::QofInstance * for each object
- of this type in the target book */
- QofBook *mergeBook; /**< pointer to the import book for this
- merge operation. */
- QofBook *targetBook; /**< pointer to the target book for this
- merge operation. */
- gboolean abort; /**< set to TRUE if MERGE_INVALID is set. */
- QofBookMergeRule *currentRule; /**< placeholder for the rule currently
- being tested or applied. */
- GSList *orphan_list; /**< List of QofInstance's that need to be rematched.
-
- When one QofInstance has a lower difference to the targetEnt than the
- previous best_match, the new match takes precedence. This list holds those
- orphaned entities that are not a good enough match so that these can be
- rematched later. The ranking is handled using the private QofInstanceRating
- struct and the GHashTable ::QofBookMergeData::target_table.
- */
- GHashTable *target_table; /**< The GHashTable to hold the
- QofInstanceRating values. */
-
-} QofBookMergeData;
-
-
-/* ======================================================================== */
-/** @name qof_book_merge API
- @{
-*/
-/** \brief Initialise the QofBookMerge process
-
- First function of the QofBookMerge API. Every merge must begin with init.
-
- Requires the book to import (::QofBook *) and the book to receive the
- import, the target book (::QofBook *). Returns a pointer to
- ::QofBookMergeData which must be checked for a NULL before continuing. \n
-Process:
-
- -# Invoke the callback ::qof_book_merge_foreach_type on every registered
- object class definition.
- -# Callback obtains the registered parameter list for each object type.
- This provides run time access to all registered objects and all object
- parameters without any changes to QofBookMerge - no registered object or
- parameter is omitted from any merge operation.
- -# Use ::qof_object_foreach to invoke the callback ::qof_book_merge_foreach,
- one object at a time on every instance stored in mergeBook. This is the
- first point where real data from the import book is accessed.
- -# qof_book_merge_foreach obtains the ::GncGUID for the object from the import
- book and runs the first check on the original book, checking for any exact
- GncGUID match. With the full parameter list, the rules for this object can be
- created. If there is a GncGUID match, the data in each parameter of the import
- object is compared with the same semantic object in the original book. If
- there is no GncGUID in the import object or no GncGUID match with the original
- book, the original book is searched to find a parameter match - checking
- for a ::MERGE_DUPLICATE result.
- -# ::qof_book_merge_compare sets the ::QofBookMergeResult of the comparison.
- -# Inserts the completed rule into QofBookMergeData::mergeList GSList.
-
-\return NULL in case of error, otherwise a ::QofBookMergeData* metadata context.
-
-*/
-QofBookMergeData*
-qof_book_merge_init( QofBook *importBook, QofBook *targetBook);
-
-
-/** \brief Definition of the dialogue control callback routine
-
-All ::MERGE_REPORT rules must be offered for user intervention using this
-template.\n
-Commit will fail if any rules are still tagged as \a MERGE_REPORT.
-
-Calling processes are free to also offer MERGE_NEW, MERGE_UPDATE,
-MERGE_DUPLICATE and MERGE_ABSOLUTE for user intervention. Attempting to query
-MERGE_INVALID rules will cause an error.
-
-For an example, consider test_rule_loop, declared as:
-
-<tt>void test_rule_loop(QofBookMergeData *mergeData, QofBookMergeRule *rule, guint remainder);\n
-void test_rule_loop(QofBookMergeData *mergeData, QofBookMergeRule *rule, guint remainder) \n
-{\n
- g_return_if_fail(rule != NULL);\n
- g_return_if_fail(mergeData != NULL);
- printf("Rule Result %s", rule->mergeType);\n
- qof_book_merge_update_result(mergeData, rule, MERGE_UPDATE);\n
-}</tt>
-
-The dialogue is free to call ::qof_book_merge_update_result in the loop or at the end
-as long as the link between the rule and the result is maintained, e.g. by using a
-GHashTable.
-\n
-The parameters are:
- - data : pointer to the ::QofBookMergeData metadata context returned by init.
- - rule : pointer to the ::QofBookMergeRule that generated the collision report
- - remainder : guint value returned from g_slist_length for the number of other
- rules remaining with the same result. This might be useful for a
- progress dialogue, it might not. When updating MERGE_REPORT,
- remainder must equal zero before calling ::qof_book_merge_commit or
- the import will abort.
-\n
-
-If the dialogue sets \b any rule result to ::MERGE_INVALID, the import will
-abort when ::qof_book_merge_commit is called. It is the responsibility of
-the calling function to handle the error code from ::qof_book_merge_commit,
-close the dialogue and return. The merge routines in these files will already
-have halted the merge operation and freed any memory allocated to merge
-structures before returning the error code. There is no need for the dialogue
-process to report back to QofBookMerge in this situation.
-*/
-typedef void (* QofBookMergeRuleForeachCB)( QofBookMergeData*, QofBookMergeRule*, guint);
-
-/** \brief Dialogue Control Callback
-
-This function is designed to be used to iterate over all rules tagged with a
-specific ::QofBookMergeResult value.
-
- at param callback external loop of type QofBookMergeRuleForeachCB
- at param mergeResult ::QofBookMergeResult value to look up.
- at param mergeData ::QofBookMergeData merge context.
-
-\b Note : MERGE_NEW causes a new entity to be created in the target book at
-commit which is then assigned as the targetEnt of that rule. If
-mergeResult == MERGE_NEW, the rules returned by qof_book_merge_rule_foreach
-will have a NULL set for the targetEnt. This is because commit has not yet
-been called and no changes can be made to the target book. The calling
-process must handle the NULL targetEnt and NOT call any param_getfcn
-routines for the target entity. The import entity is available for display.
-
-Uses ::qof_book_get_collection with the QofBookMergeRule::mergeType object
-type to return a collection of ::QofInstance entities from either the
-QofBookMergeData::mergeBook or QofBookMergeData::targetBook. Then
-uses ::qof_collection_lookup_entity to lookup the QofBookMergeRule::importEnt
-and again the QofBookMergeRule::targetEnt to return the two specific entities.
-
-*/
-void qof_book_merge_rule_foreach( QofBookMergeData* mergeData,
- QofBookMergeRuleForeachCB callback ,
- QofBookMergeResult mergeResult);
-
-/** \brief provides easy string access to parameter data for dialogue use
-
-Uses the param_getfcn to retrieve the parameter value as a string, suitable for
-display in dialogues and user intervention output. Within a QofBookMerge context,
-only the parameters used in the merge are available, i.e. parameters where both
-param_getfcn and param_setfcn are not NULL.
-
-Note that the object type description (a full text version of the object name) is
-also available to the dialogue as QofBookMergeRule::mergeLabel.
-
-This allows the dialog to display the description of the object and all
-parameter data.
-
-*/
-gchar* qof_book_merge_param_as_string(QofParam *qtparam, QofInstance *qtEnt);
-
-/** \brief called by dialogue callback to set the result of user intervention
-
-Set \b any rule result to ::MERGE_INVALID to abort the import when
-::qof_book_merge_commit is called, without changing the target book.
-
-The calling process should make it absolutely clear that a merge operation
-\b cannot be undone and that a backup copy should always be available
-\b before a merge is initialised.
-
-Recommended method: Only offer three options to the user per rule:
-
--# Allow import data to be merged into target data
- - change MERGE_REPORT to MERGE_UPDATE
--# Allow import data without an exact match to be
- added as new
- - change MERGE_REPORT to MERGE_NEW \b IF mergeAbsolute = FALSE
--# Ignore import data and leave target data unchanged
- - change MERGE_REPORT to MERGE_ABSOLUTE or MERGE_DUPLICATE
-
-Handle the required result changes in code: Check the value of
-QofBookMergeRule::mergeAbsolute and use these principles:
-
-To ignore entities tagged as:
-- MERGE_REPORT, you must check the value of mergeAbsolute.
- - if mergeAbsolute is TRUE, change MERGE_REPORT to MERGE_ABSOLUTE
- - if mergeAbsolute is FALSE, change MERGE_REPORT to MERGE_DUPLICATE
-- MERGE_NEW, set MERGE_DUPLICATE.
-- MERGE_UPDATE, you must check the value of mergeAbsolute.
- - if mergeAbsolute is TRUE, change MERGE_UPDATE to MERGE_ABSOLUTE
- - if mergeAbsolute is FALSE, change MERGE_UPDATE to MERGE_DUPLICATE
-
-To merge entities that are not pre-set to MERGE_NEW, set MERGE_UPDATE.\n
-Attempting to merge an entity when the pre-set value was MERGE_NEW will
-force a change back to MERGE_NEW because no suitable target exists for the
-merge.
-
-To add entities, check mergeAbsolute is FALSE and set MERGE_NEW.\n
-An entity \b only be added if mergeAbsolute is FALSE. Attempting to
-add an entity when mergeAbsolute is TRUE will always force a MERGE_UPDATE.
-
-It is not possible to update the same rule more than once.
-
--# \b MERGE_NEW is reserved for new objects and is only pre-set if
-all parameters, including GncGUID, have already failed to match any
-relevant object. ::qof_book_merge_commit will create new
-entities for all rules tagged as MERGE_NEW.
- - if mergeAbsolute is TRUE and the user wants to import the
- data, requests to set MERGE_NEW will be forced to MERGE_UPDATE
- because an entity with that GncGUID already exists in the target book.
- - if MERGE_NEW is pre-set, requests to change to MERGE_UPDATE will be
- ignored because a new entity is needed.
--# \b MERGE_UPDATE is reserved for existing objects - ::qof_book_merge_commit
-will require a matching entity to update and will force a change to back to
-MERGE_NEW if none is known to exist, using the principle above.
--# \b MERGE_INVALID will cause an abort of the merge process.
--# \b MERGE_UNDEF and \b MERGE_REPORT cannot be set - the entity result will
-be unchanged.
--# \b MERGE_DUPLICATE and \b MERGE_ABSOLUTE are handled identically but are
- semantically different - QofBookMergeRule::mergeAbsolute is used to
- dictate which to set:
- - if mergeAbsolute is TRUE but MERGE_DUPLICATE is requested,
- force a change to MERGE_ABSOLUTE.
- - if mergeAbsolute is FALSE but MERGE_ABSOLUTE is requested,
- force a change to MERGE_DUPLICATE.
-
-::qof_book_merge_commit only commits entities tagged
-with MERGE_NEW and MERGE_UPDATE results.
-\n
-Entities tagged with MERGE_ABSOLUTE and MERGE_DUPLICATE results are ignored.
-
-The calling process must check the return value and call
-::qof_book_merge_abort(mergeData) if non-zero.
-
- at param mergeData the merge context, ::QofBookMergeData*
- at param tag the result to attempt to set, ::QofBookMergeResult
-
-\return -1 if supplied parameters are invalid or NULL, 0 on success.
-
-*/
-QofBookMergeData*
-qof_book_merge_update_result(QofBookMergeData *mergeData, QofBookMergeResult tag);
-
-/** \brief Commits the import data to the target book
-
- The last function in the API and the final part of any QofBookMerge operation.
-
-qof_book_merge_commit will abort the \b entire merge operation if any rule
-is set to ::MERGE_INVALID. It is the responsibility of the calling
-function to handle the error code from ::qof_book_merge_commit, close the
-dialogue and return. qof_book_merge_commit will already have halted the merge
-operation and freed any memory allocated to all merge structures before
-returning the error code. There is no way for the dialogue process to report
-back to qof_book_merge in this situation.
-
-qof_book_merge_commit checks for any entities still tagged as
-::MERGE_REPORT and then proceeds to import all entities tagged as
-::MERGE_UPDATE or ::MERGE_NEW into the target book.
-\n
-<b>This final process cannot be UNDONE!</b>\n
-\n
-
- at param mergeData the merge context, ::QofBookMergeData*
-
-\return
- - -2 if any rules are tagged as ::MERGE_INVALID
- - mergeData will have been g_free'd).
- - note that this will be before any operations are done on the target
- QofBook.
- - -1 if mergeData is invalid or no merge has been initialised with
- ::qof_book_merge_init - the calling process must check the value of
- mergeData
- - +1 if some entities are still tagged as \a MERGE_REPORT - use
- ::qof_book_merge_update_rule and try again (mergeData is retained).
- - 0 on success - mergeData will have been freed.
-*/
-gint
-qof_book_merge_commit(QofBookMergeData *mergeData );
-
-/** \brief Abort the merge and free all memory allocated by the merge
-
-Sometimes, setting ::MERGE_INVALID is insufficient: e.g. if the user aborts the
-merge from outside the functions dealing with the merge ruleset. This function
-causes an immediate abort - the calling process must start again at Init if
-a new merge is required.
-*/
-void
-qof_book_merge_abort(QofBookMergeData *mergeData);
-
-#endif // QOFBOOKMERGE_H
-/** @} */
-/** @} */
More information about the gnucash-changes
mailing list