r16055 - gnucash/trunk/lib/libqof/qof - Fix several problems with the QOF book merge code. Use unique error

David Hampton hampton at cvs.gnucash.org
Sat May 5 20:27:44 EDT 2007


Author: hampton
Date: 2007-05-05 20:27:43 -0400 (Sat, 05 May 2007)
New Revision: 16055
Trac: http://svn.gnucash.org/trac/changeset/16055

Modified:
   gnucash/trunk/lib/libqof/qof/qofbookmerge.c
Log:
Fix several problems with the QOF book merge code.  Use unique error
codes in the qof_book_merge_commit() function.  Fixes 343730.


Modified: gnucash/trunk/lib/libqof/qof/qofbookmerge.c
===================================================================
--- gnucash/trunk/lib/libqof/qof/qofbookmerge.c	2007-05-05 23:25:58 UTC (rev 16054)
+++ gnucash/trunk/lib/libqof/qof/qofbookmerge.c	2007-05-06 00:27:43 UTC (rev 16055)
@@ -105,6 +105,8 @@
 	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);
@@ -248,6 +250,11 @@
 		}
 		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 = 
@@ -263,6 +270,8 @@
 	mergeData->currentRule = currentRule;
 	g_free(kvpImport);
 	g_free(kvpTarget);
+
+	LEAVE (" ");
 	return 0;
 }
 
@@ -279,10 +288,9 @@
 }
 
 static void
-qof_book_merge_commit_foreach (
-			QofBookMergeRuleForeachCB cb, 
-			QofBookMergeResult mergeResult,
-			QofBookMergeData *mergeData)
+qof_book_merge_commit_foreach (QofBookMergeRuleForeachCB cb, 
+                               QofBookMergeResult mergeResult,
+                               QofBookMergeData *mergeData)
 {
 	struct QofBookMergeRuleIterate iter;
 	QofBookMergeRule *currentRule;
@@ -346,7 +354,7 @@
 
 static void
 qof_book_merge_orphan_check(double difference, QofBookMergeRule *mergeRule, 
-    QofBookMergeData *mergeData)
+                            QofBookMergeData *mergeData)
 {
 	/* Called when difference is lower than previous
 		Lookup target to find previous match
@@ -375,6 +383,8 @@
 	QofInstance *best_matchEnt;
 	double difference;
 
+	ENTER (" ");
+
 	g_return_if_fail(mergeData != NULL);
 	currentRule = mergeData->currentRule;
 	g_return_if_fail(currentRule != NULL);
@@ -406,6 +416,8 @@
 	}
 	g_slist_free(mergeData->orphan_list);
 	g_slist_free(targets);
+
+	LEAVE (" ");
 }
 
 static void 
@@ -446,13 +458,15 @@
 	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_new(QofBookMergeRule,1);
+	mergeRule = g_new0(QofBookMergeRule,1);
 	mergeRule->importEnt = 		mergeEnt;
 	mergeRule->difference = 	difference = 0;
 	mergeRule->mergeAbsolute = 	FALSE;
@@ -532,6 +546,8 @@
 	mergeData->mergeList = g_list_prepend(mergeData->mergeList,mergeRule);
 	guid_free(g);
 	/* return to qof_book_merge_init */
+
+	LEAVE (" ");
 }
 
 static void 
@@ -583,17 +599,80 @@
 	iter->remainder--;
 }
 
+
+/**
+ * Creates an object when the MergeResult is MERGE_NEW. Called for each MergeRule.
+ */
 static void 
-qof_book_merge_commit_rule_loop(
-						QofBookMergeData *mergeData,
-						QofBookMergeRule *rule, 
-						guint remainder) 
+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 GUID 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(QofBookMergeData *mergeData, 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) 
 { 
-	QofInstance *inst;
 	gboolean    registered_type;
 	QofInstance   *referenceEnt;
 	/* cm_ prefix used for variables that hold the data to commit */
-	QofCollection *cm_coll;
+	QofCollection *cm_coll, *mapped_coll;
+	QofBookMergeMapCollectionIterate mapped_coll_iter;
 	QofParam    *cm_param;
 	gchar       *cm_string;
 	const GUID  *cm_guid;
@@ -624,14 +703,15 @@
 	g_return_if_fail(mergeData != NULL);
 	g_return_if_fail(mergeData->targetBook != NULL);
 	g_return_if_fail((rule->mergeResult != MERGE_NEW)||(rule->mergeResult != MERGE_UPDATE));
-	/* create a new object for MERGE_NEW */
-	/* The new object takes the GUID from the import to retain an absolute match */
-	if(rule->mergeResult == MERGE_NEW) {
-		inst = (QofInstance*)qof_object_new_instance(rule->importEnt->e_type, mergeData->targetBook);
-		g_return_if_fail(inst != NULL);
-		rule->targetEnt = inst;
-		qof_instance_set_guid(rule->targetEnt, qof_instance_get_guid(rule->importEnt));
-	}
+
+	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 GUID match or
 		2. by best_matchEnt and difference or
@@ -642,6 +722,10 @@
 		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;
@@ -712,12 +796,20 @@
 		}
 		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, cm_coll); }
+			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) 
 			{ 
@@ -727,6 +819,13 @@
 		}
 		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) 
@@ -748,8 +847,10 @@
 	QofBookMergeRule *currentRule;
 	GList *node;
 
+	ENTER (" ");
+
 	g_return_val_if_fail((importBook != NULL)&&(targetBook != NULL), NULL);
-	mergeData = g_new(QofBookMergeData, 1);
+	mergeData = g_new0(QofBookMergeData, 1);
 	mergeData->abort = FALSE;
 	mergeData->mergeList = NULL;
 	mergeData->targetList = NULL;
@@ -758,7 +859,7 @@
 	mergeData->mergeObjectParams = NULL;
 	mergeData->orphan_list = NULL;
 	mergeData->target_table = g_hash_table_new( g_direct_hash, qof_book_merge_rule_cmp);
-	currentRule = g_new(QofBookMergeRule, 1);
+	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);
@@ -773,6 +874,8 @@
 			return(NULL);
 		}
 	}
+
+	LEAVE (" ");
 	return mergeData;
 }
 
@@ -899,8 +1002,8 @@
 }
 
 QofBookMergeData*
-qof_book_merge_update_result(QofBookMergeData *mergeData,
-						QofBookMergeResult tag)
+qof_book_merge_update_result (QofBookMergeData *mergeData,
+                              QofBookMergeResult tag)
 {
 	QofBookMergeRule *resolved;
 
@@ -942,14 +1045,17 @@
 	QofBookMergeRule *currentRule;
 	GList *check, *node;
 
-	g_return_val_if_fail(mergeData != NULL, -1);
-	g_return_val_if_fail(mergeData->mergeList != NULL, -1);
-	g_return_val_if_fail(mergeData->targetBook != NULL, -1);
-	if(mergeData->abort == TRUE) return -1;
+	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, -1);
+	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);
@@ -961,10 +1067,13 @@
 		}
 	}
 	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) {
@@ -979,13 +1088,15 @@
 	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 )
+qof_book_merge_rule_foreach (QofBookMergeData *mergeData, 
+                             QofBookMergeRuleForeachCB cb, 
+                             QofBookMergeResult mergeResult )
 {
 	struct QofBookMergeRuleIterate iter;
 	QofBookMergeRule *currentRule;



More information about the gnucash-changes mailing list