32 struct QofBookMergeRuleIterate
47 #define DEFAULT_MERGE_WEIGHT 1 48 #define QOF_STRING_WEIGHT 3 49 #define QOF_DATE_STRING_LENGTH MAX_DATE_LENGTH 60 if (absolute && !match)
64 if (!absolute && !match)
75 GSList *linkedEntList;
79 collect_reference_cb (
QofEntity * ent, gpointer user_data)
81 struct collect_list_s *s;
83 s = (
struct collect_list_s *) user_data;
86 s->linkedEntList = g_slist_prepend (s->linkedEntList, ent);
94 gchar *stringImport, *stringTarget;
95 QofEntity *mergeEnt, *targetEnt, *referenceEnt;
96 const GUID *guidImport, *guidTarget;
102 gboolean G_GNUC_UNUSED absolute, G_GNUC_UNUSED mergeError, knowntype, mergeMatch, booleanImport,
105 (*numeric_getter) (QofEntity *,
QofParam *);
106 gdouble doubleImport, doubleTarget, (*double_getter) (QofEntity *,
108 gint32 i32Import, i32Target, (*int32_getter) (QofEntity *,
QofParam *);
109 gint64 i64Import, i64Target, (*int64_getter) (QofEntity *,
QofParam *);
110 gchar charImport, charTarget, (*char_getter) (QofEntity *,
QofParam *);
112 g_return_val_if_fail ((mergeData != NULL), -1);
114 g_return_val_if_fail ((currentRule != NULL), -1);
122 g_return_val_if_fail ((targetEnt) || (mergeEnt) || (paramList), -1);
126 while (paramList != NULL)
130 qtparam = paramList->data;
131 mergeParamName = qtparam->param_name;
132 g_return_val_if_fail (mergeParamName != NULL, -1);
133 mergeType = qtparam->param_type;
136 stringImport = qtparam->param_getfcn (mergeEnt, qtparam);
137 stringTarget = qtparam->param_getfcn (targetEnt, qtparam);
139 if (stringImport == NULL)
141 if (stringTarget == NULL)
146 currentRule = qof_book_merge_update_rule (currentRule,
147 mergeMatch, QOF_STRING_WEIGHT);
148 stringImport = stringTarget = NULL;
155 qtImport = qtparam->param_getfcn (mergeEnt, qtparam);
156 qtTarget = qtparam->param_getfcn (targetEnt, qtparam);
158 currentRule = qof_book_merge_update_rule (currentRule,
159 mergeMatch, DEFAULT_MERGE_WEIGHT);
162 if ((
safe_strcmp (mergeType, QOF_TYPE_NUMERIC) == 0) ||
168 numericImport = numeric_getter (mergeEnt, qtparam);
169 numericTarget = numeric_getter (targetEnt, qtparam);
172 currentRule = qof_book_merge_update_rule (currentRule,
173 mergeMatch, DEFAULT_MERGE_WEIGHT);
178 guidImport = qtparam->param_getfcn (mergeEnt, qtparam);
179 guidTarget = qtparam->param_getfcn (targetEnt, qtparam);
180 if (guid_compare (guidImport, guidTarget) == 0)
182 currentRule = qof_book_merge_update_rule (currentRule,
183 mergeMatch, DEFAULT_MERGE_WEIGHT);
189 (gint32 (*)(QofEntity *,
191 i32Import = int32_getter (mergeEnt, qtparam);
192 i32Target = int32_getter (targetEnt, qtparam);
193 if (i32Target == i32Import)
195 currentRule = qof_book_merge_update_rule (currentRule,
196 mergeMatch, DEFAULT_MERGE_WEIGHT);
202 (gint64 (*)(QofEntity *,
204 i64Import = int64_getter (mergeEnt, qtparam);
205 i64Target = int64_getter (targetEnt, qtparam);
206 if (i64Target == i64Import)
208 currentRule = qof_book_merge_update_rule (currentRule,
209 mergeMatch, DEFAULT_MERGE_WEIGHT);
215 (double (*)(QofEntity *,
217 doubleImport = double_getter (mergeEnt, qtparam);
218 doubleTarget = double_getter (mergeEnt, qtparam);
219 if (doubleImport == doubleTarget)
221 currentRule = qof_book_merge_update_rule (currentRule,
222 mergeMatch, DEFAULT_MERGE_WEIGHT);
225 if (
safe_strcmp (mergeType, QOF_TYPE_BOOLEAN) == 0)
228 (gboolean (*)(QofEntity *,
230 booleanImport = boolean_getter (mergeEnt, qtparam);
231 booleanTarget = boolean_getter (targetEnt, qtparam);
232 if (booleanImport != FALSE && booleanImport != TRUE)
233 booleanImport = FALSE;
234 if (booleanTarget != FALSE && booleanTarget != TRUE)
235 booleanTarget = FALSE;
236 if (booleanImport == booleanTarget)
238 currentRule = qof_book_merge_update_rule (currentRule,
239 mergeMatch, DEFAULT_MERGE_WEIGHT);
251 currentRule = qof_book_merge_update_rule (currentRule,
252 mergeMatch, DEFAULT_MERGE_WEIGHT);
258 (gchar (*)(QofEntity *,
QofParam *)) qtparam->param_getfcn;
259 charImport = char_getter (mergeEnt, qtparam);
260 charTarget = char_getter (targetEnt, qtparam);
261 if (charImport == charTarget)
263 currentRule = qof_book_merge_update_rule (currentRule,
264 mergeMatch, DEFAULT_MERGE_WEIGHT);
273 struct collect_list_s s;
274 s.linkedEntList = NULL;
275 mergeColl = qtparam->param_getfcn (mergeEnt, qtparam);
276 targetColl = qtparam->param_getfcn (targetEnt, qtparam);
282 currentRule = qof_book_merge_update_rule (currentRule,
283 mergeMatch, DEFAULT_MERGE_WEIGHT);
288 referenceEnt = qtparam->param_getfcn (mergeEnt, qtparam);
291 if (referenceEnt == qtparam->param_getfcn (targetEnt, qtparam))
295 if (knowntype == FALSE)
297 referenceEnt = qtparam->param_getfcn (mergeEnt, qtparam);
298 if ((referenceEnt != NULL)
299 && (
safe_strcmp (referenceEnt->e_type, mergeType) == 0))
305 qtparam->param_getfcn (targetEnt, qtparam))
307 currentRule = qof_book_merge_update_rule (currentRule,
308 mergeMatch, DEFAULT_MERGE_WEIGHT);
311 paramList = g_slist_next (paramList);
320 qof_book_merge_commit_foreach_cb (gpointer rule, gpointer arg)
322 struct QofBookMergeRuleIterate *qiter;
324 g_return_if_fail (arg != NULL);
325 qiter = (
struct QofBookMergeRuleIterate *) arg;
326 g_return_if_fail (qiter->data != NULL);
336 struct QofBookMergeRuleIterate qiter;
338 GList *subList, *node;
340 g_return_if_fail (cb != NULL);
341 g_return_if_fail (mergeData != NULL);
343 g_return_if_fail (currentRule != NULL);
344 g_return_if_fail (mergeResult > 0);
351 qiter.ruleList = NULL;
352 for (node = mergeData->
mergeList; node != NULL; node = node->next)
354 currentRule = node->data;
355 if (currentRule->mergeResult == mergeResult)
356 subList = g_list_prepend (subList, currentRule);
358 qiter.remainder = g_list_length (subList);
359 qiter.data = mergeData;
360 g_list_foreach (subList, qof_book_merge_commit_foreach_cb, &qiter);
390 qof_book_merge_rule_cmp (gconstpointer a, gconstpointer b)
401 qof_book_merge_orphan_check (
double difference,
409 g_return_if_fail (mergeRule != NULL);
410 g_return_if_fail (mergeData != NULL);
430 GSList *orphans, *targets;
432 QofEntity * G_GNUC_UNUSED best_matchEnt;
435 g_return_if_fail (mergeData != NULL);
437 g_return_if_fail (currentRule != NULL);
441 targets = g_slist_copy (mergeData->
targetList);
442 while (orphans != NULL)
444 rule = orphans->data;
445 g_return_if_fail (rule != NULL);
452 g_list_prepend (mergeData->
mergeList, rule);
453 orphans = g_slist_next (orphans);
457 g_return_if_fail (qof_book_merge_compare (mergeData) != -1);
464 g_list_prepend (mergeData->
mergeList, rule);
465 qof_book_merge_orphan_check (difference, rule, mergeData);
467 orphans = g_slist_next (orphans);
470 g_slist_free (targets);
474 qof_book_merge_foreach_target (QofEntity * targetEnt, gpointer user_data)
478 g_return_if_fail (user_data != NULL);
480 g_return_if_fail (targetEnt != NULL);
482 g_slist_prepend (mergeData->
targetList, targetEnt);
486 qof_book_merge_foreach_type_target (
QofObject * merge_obj,
492 g_return_if_fail (user_data != NULL);
495 g_return_if_fail (currentRule != NULL);
496 g_return_if_fail (merge_obj != NULL);
502 qof_book_merge_foreach_target, user_data);
507 qof_book_merge_foreach (QofEntity * mergeEnt, gpointer user_data)
511 QofEntity *targetEnt, *best_matchEnt;
516 g_return_if_fail (user_data != NULL);
518 g_return_if_fail (mergeEnt != NULL);
520 g_return_if_fail (currentRule != NULL);
534 targetEnt = best_matchEnt = NULL;
537 (mergeData->
targetBook, mergeEnt->e_type), g);
538 if (targetEnt != NULL)
542 g_return_if_fail (qof_book_merge_compare (mergeData) != -1);
546 g_list_prepend (mergeData->
mergeList, mergeRule);
554 if (g_slist_length (mergeData->
targetList) == 0)
556 difference = g_slist_length (mergeRule->
mergeParam);
561 currentRule = mergeRule;
563 g_return_if_fail (qof_book_merge_compare (mergeData) != -1);
587 qof_book_merge_orphan_check (difference, mergeRule, mergeData);
589 c = g_slist_next (c);
592 if (best_matchEnt != NULL)
601 g_return_if_fail (qof_book_merge_compare (mergeData) != -1);
614 g_list_prepend (mergeData->
mergeList, mergeRule);
620 qof_book_merge_foreach_param (
QofParam * param, gpointer user_data)
624 g_return_if_fail (user_data != NULL);
626 g_return_if_fail (param != NULL);
627 if ((param->param_getfcn != NULL) && (param->param_setfcn != NULL))
635 qof_book_merge_foreach_type (
QofObject * merge_obj, gpointer user_data)
639 g_return_if_fail (user_data != NULL);
641 g_return_if_fail ((merge_obj != NULL));
643 if ((merge_obj->
create == NULL) || (merge_obj->
foreach == NULL))
645 DEBUG (
" merge_obj QOF support failed %s", merge_obj->e_type);
652 qof_book_merge_foreach_param, mergeData);
654 qof_book_merge_foreach, mergeData);
658 qof_book_merge_rule_cb (gpointer rule, gpointer arg)
660 struct QofBookMergeRuleIterate *qiter;
663 g_return_if_fail (arg != NULL);
664 qiter = (
struct QofBookMergeRuleIterate *) arg;
665 mergeData = qiter->data;
666 g_return_if_fail (mergeData != NULL);
667 g_return_if_fail (mergeData->
abort == FALSE);
669 qiter->data = mergeData;
678 gboolean registered_type;
679 QofEntity *referenceEnt;
689 gdouble cm_double, (*double_getter) (QofEntity *,
QofParam *);
690 gboolean cm_boolean, (*boolean_getter) (QofEntity *,
QofParam *);
691 gint32 cm_i32, (*int32_getter) (QofEntity *,
QofParam *);
692 gint64 cm_i64, (*int64_getter) (QofEntity *,
QofParam *);
693 gchar cm_char, (*char_getter) (QofEntity *,
QofParam *);
695 void (*string_setter) (QofEntity *,
const gchar *);
696 void (*time_setter) (QofEntity *,
QofTime *);
697 void (*numeric_setter) (QofEntity *,
QofNumeric);
698 void (*guid_setter) (QofEntity *,
const GUID *);
699 void (*double_setter) (QofEntity *, double);
700 void (*boolean_setter) (QofEntity *, gboolean);
701 void (*i32_setter) (QofEntity *, gint32);
702 void (*i64_setter) (QofEntity *, gint64);
703 void (*char_setter) (QofEntity *, gchar);
704 void (*kvp_frame_setter) (QofEntity *,
KvpFrame *);
705 void (*reference_setter) (QofEntity *, QofEntity *);
708 g_return_if_fail (rule != NULL);
709 g_return_if_fail (mergeData != NULL);
710 g_return_if_fail (mergeData->
targetBook != NULL);
720 g_return_if_fail (inst != NULL);
732 registered_type = FALSE;
738 cm_string = cm_param->param_getfcn (rule->
importEnt, cm_param);
740 (void (*)(QofEntity *,
741 const gchar *)) cm_param->param_setfcn;
742 if (string_setter != NULL)
743 string_setter (rule->
targetEnt, cm_string);
744 registered_type = TRUE;
753 time_getter (rule->
importEnt, cm_param));
755 (void (*)(QofEntity *,
QofTime *))
756 cm_param->param_setfcn;
757 if ((time_setter != NULL) && (qof_time_is_valid (cm_qt)))
759 registered_type = TRUE;
767 cm_numeric = numeric_getter (rule->
importEnt, cm_param);
769 (void (*)(QofEntity *,
771 if (numeric_setter != NULL)
772 numeric_setter (rule->
targetEnt, cm_numeric);
773 registered_type = TRUE;
777 cm_guid = cm_param->param_getfcn (rule->
importEnt, cm_param);
779 (void (*)(QofEntity *,
780 const GUID *)) cm_param->param_setfcn;
781 if (guid_setter != NULL)
783 registered_type = TRUE;
788 (gint32 (*)(QofEntity *,
789 QofParam *)) cm_param->param_getfcn;
790 cm_i32 = int32_getter (rule->
importEnt, cm_param);
792 (void (*)(QofEntity *, gint32)) cm_param->param_setfcn;
793 if (i32_setter != NULL)
795 registered_type = TRUE;
800 (gint64 (*)(QofEntity *,
801 QofParam *)) cm_param->param_getfcn;
802 cm_i64 = int64_getter (rule->
importEnt, cm_param);
804 (void (*)(QofEntity *, gint64)) cm_param->param_setfcn;
805 if (i64_setter != NULL)
807 registered_type = TRUE;
812 (double (*)(QofEntity *,
813 QofParam *)) cm_param->param_getfcn;
814 cm_double = double_getter (rule->
importEnt, cm_param);
816 (void (*)(QofEntity *, double)) cm_param->param_setfcn;
817 if (double_setter != NULL)
818 double_setter (rule->
targetEnt, cm_double);
819 registered_type = TRUE;
824 (gboolean (*)(QofEntity *,
QofParam *)) cm_param->
826 cm_boolean = boolean_getter (rule->
importEnt, cm_param);
828 (void (*)(QofEntity *, gboolean)) cm_param->param_setfcn;
829 if (boolean_setter != NULL)
830 boolean_setter (rule->
targetEnt, cm_boolean);
831 registered_type = TRUE;
837 param_getfcn (rule->
importEnt, cm_param));
839 (void (*)(QofEntity *,
KvpFrame *)) cm_param->param_setfcn;
840 if (kvp_frame_setter != NULL)
841 kvp_frame_setter (rule->
targetEnt, cm_kvp);
842 registered_type = TRUE;
847 (gchar (*)(QofEntity *,
848 QofParam *)) cm_param->param_getfcn;
849 cm_char = char_getter (rule->
importEnt, cm_param);
851 (void (*)(QofEntity *, gchar)) cm_param->param_setfcn;
852 if (char_setter != NULL)
854 registered_type = TRUE;
858 cm_coll = cm_param->param_getfcn (rule->
importEnt, cm_param);
862 if (collection_setter != NULL)
863 collection_setter (rule->
targetEnt, cm_coll);
864 registered_type = TRUE;
869 cm_param->param_getfcn (rule->
importEnt, cm_param);
871 (void (*)(QofEntity *,
872 QofEntity *)) cm_param->param_setfcn;
873 if (reference_setter != NULL)
874 reference_setter (rule->
targetEnt, referenceEnt);
875 registered_type = TRUE;
877 if (registered_type == FALSE)
880 cm_param->param_getfcn (rule->
importEnt, cm_param);
884 (void (*)(QofEntity *, QofEntity *)) cm_param->
886 if (reference_setter != NULL)
888 reference_setter (rule->
targetEnt, referenceEnt);
906 g_return_val_if_fail ((importBook != NULL)
907 && (targetBook != NULL), NULL);
909 mergeData->
abort = FALSE;
917 g_hash_table_new (g_direct_hash, qof_book_merge_rule_cmp);
923 qof_book_merge_match_orphans (mergeData);
924 for (check = mergeData->
mergeList; check != NULL; check = check->next)
926 currentRule = check->data;
929 mergeData->
abort = TRUE;
941 g_return_if_fail (mergeData != NULL);
944 currentRule = mergeData->
mergeList->data;
952 g_free (currentRule);
971 g_return_val_if_fail ((mergeData != NULL), NULL);
972 g_return_val_if_fail ((tag > 0), NULL);
975 g_return_val_if_fail ((resolved != NULL), NULL);
984 if (resolved->
updated == FALSE)
989 mergeData->
abort = TRUE;
1001 GList *check, *node;
1003 g_return_val_if_fail (mergeData != NULL, -1);
1004 g_return_val_if_fail (mergeData->
mergeList != NULL, -1);
1005 g_return_val_if_fail (mergeData->
targetBook != NULL, -1);
1006 if (mergeData->
abort == TRUE)
1008 check = g_list_copy (mergeData->
mergeList);
1009 g_return_val_if_fail (check != NULL, -1);
1010 for (node = check; node != NULL; node = node->next)
1012 currentRule = node->data;
1016 g_list_free (check);
1021 g_list_free (check);
1025 g_list_free (check);
1026 qof_book_merge_commit_foreach (qof_book_merge_commit_rule_loop,
1028 qof_book_merge_commit_foreach (qof_book_merge_commit_rule_loop,
1034 currentRule = mergeData->
mergeList->data;
1053 struct QofBookMergeRuleIterate qiter;
1055 GList *matching_rules, *node;
1057 g_return_if_fail (cb != NULL);
1058 g_return_if_fail (mergeData != NULL);
1060 g_return_if_fail (mergeResult > 0);
1062 g_return_if_fail (mergeData->
abort == FALSE);
1064 qiter.data = mergeData;
1065 matching_rules = NULL;
1066 for (node = mergeData->
mergeList; node != NULL; node = node->next)
1068 currentRule = node->data;
1069 if (currentRule->mergeResult == mergeResult)
1070 matching_rules = g_list_prepend (matching_rules,
1073 qiter.remainder = g_list_length (matching_rules);
1074 g_list_foreach (matching_rules, qof_book_merge_rule_cb, &qiter);
1075 g_list_free (matching_rules);
gpointer qof_object_new_instance(QofIdTypeConst type_name, QofBook *book)
gint qof_collection_compare(QofCollection *target, QofCollection *merge)
Compare two secondary collections.
#define QOF_TYPE_COLLECT
secondary collections are used for one-to-many references between entities and are implemented using ...
gint qof_numeric_compare(QofNumeric a, QofNumeric b)
QofCollection * qof_book_get_collection(QofBook *book, QofIdType entity_type)
struct _QofNumeric QofNumeric
A rational-number type.
void qof_class_param_foreach(QofIdTypeConst obj_name, QofParamForeachCB cb, gpointer user_data)
gint qof_book_merge_commit(QofBookMergeData *mergeData)
Commits the import data to the target book.
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofEntityForeachCB cb, gpointer user_data)
gint kvp_frame_compare(const KvpFrame *fa, const KvpFrame *fb)
KvpFrame * kvp_frame_copy(const KvpFrame *frame)
struct _KvpFrame KvpFrame
QofTime * qof_time_copy(const QofTime *qt)
Create a copy of a QofTime.
gpointer(* create)(QofBook *)
const gchar * qof_object_get_type_label(QofIdTypeConst type_name)
struct QofCollection_s QofCollection
GHashTable * target_table
QofEntity * qof_collection_lookup_entity(QofCollection *col, const GUID *guid)
QofBookMergeResult mergeResult
void qof_collection_foreach(QofCollection *col, QofEntityForeachCB cb_func, gpointer user_data)
gint qof_time_cmp(const QofTime *ta, const QofTime *tb)
void qof_book_merge_rule_foreach(QofBookMergeData *mergeData, QofBookMergeRuleForeachCB cb, QofBookMergeResult mergeResult)
Dialogue Control Callback.
#define DEBUG(format, args...)
One rule per entity, built into a single GList for the entire merge.
QofBookMergeData * qof_book_merge_init(QofBook *importBook, QofBook *targetBook)
Initialise the QofBookMerge process.
QofBookMergeRule * currentRule
struct QofTime64 QofTime
Use a 64-bit signed int QofTime.
QofBookMergeResult
Results of collisions and user resolution.
const GUID * qof_entity_get_guid(QofEntity *ent)
void(* QofBookMergeRuleForeachCB)(QofBookMergeData *, QofBookMergeRule *, guint)
Definition of the dialogue control callback routine.
void qof_book_merge_abort(QofBookMergeData *mergeData)
Abort the merge and free all memory allocated by the merge.
GSList * mergeObjectParams
void qof_entity_set_guid(QofEntity *ent, const GUID *guid)
KvpFrame * kvp_frame_new(void)
void(* foreach)(QofCollection *, QofEntityForeachCB, gpointer)
gint safe_strcmp(const gchar *da, const gchar *db)
QofBookMergeData * qof_book_merge_update_result(QofBookMergeData *mergeData, QofBookMergeResult tag)
called by dialogue callback to set the result of user intervention
#define QOF_TYPE_CHOICE
Identify an object as containing a choice.
void qof_object_foreach_type(QofForeachTypeCB cb, gpointer user_data)
const gchar * QofLogModule
mergeData contains the essential context data for any merge.