1 /***************************************************************************
2  *            qofreference.c
3  *
4  *  Mon Feb 13 21:06:44 2006
5  *  Copyright  2006  Neil Williams
6  *  linux@codehelp.co.uk
7  ****************************************************************************/
8 /*
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22  */
23 
24 #include "config.h"
25 #include <glib.h>
26 #include "qofreference.h"
27 
28 static void
entity_set_reference_cb(QofEntity * ent,gpointer user_data)29 entity_set_reference_cb (QofEntity * ent, gpointer user_data)
30 {
31 	void (*reference_setter) (QofEntity *, QofEntity *);
32 	void (*choice_setter) (QofEntity *, QofEntity *);
33 	void (*collect_setter) (QofEntity *, QofCollection *);
34 	QofEntityReference *ref;
35 	GList *book_ref_list;
36 	QofCollection *coll;
37 	QofIdType type;
38 	QofEntity *reference;
39 	QofBook *partial_book;
40 
41 	partial_book = (QofBook *) user_data;
42 	g_return_if_fail (partial_book || ent);
43 	reference = NULL;
44 	coll = NULL;
45 	book_ref_list = qof_book_get_data (partial_book, ENTITYREFERENCE);
46 	while (book_ref_list)
47 	{
48 		ref = (QofEntityReference *) book_ref_list->data;
49 		if (0 == guid_compare (ref->ref_guid, qof_entity_get_guid (ent)))
50 		{
51 			/* avoid setting the entity's own guid as a reference. */
52 			book_ref_list = g_list_next (book_ref_list);
53 			continue;
54 		}
55 		if (qof_object_is_choice (ent->e_type))
56 		{
57 			type = ref->choice_type;
58 		}
59 		type = ref->param->param_type;
60 		coll = qof_book_get_collection (partial_book, type);
61 		reference = qof_collection_lookup_entity (coll, ref->ref_guid);
62 		reference_setter =
63 			(void (*)(QofEntity *, QofEntity *)) ref->param->param_setfcn;
64 		if ((reference) && (reference_setter))
65 		{
66 			qof_util_param_edit ((QofInstance *) ent, ref->param);
67 			qof_util_param_edit ((QofInstance *) reference, ref->param);
68 			reference_setter (ent, reference);
69 			qof_util_param_commit ((QofInstance *) ent, ref->param);
70 			qof_util_param_commit ((QofInstance *) reference, ref->param);
71 		}
72 		/* collect and choice handling */
73 		collect_setter =
74 			(void (*)(QofEntity *,
75 				QofCollection *)) ref->param->param_setfcn;
76 		choice_setter =
77 			(void (*)(QofEntity *, QofEntity *)) ref->param->param_setfcn;
78 		if ((0 == safe_strcmp (ref->param->param_type, QOF_TYPE_COLLECT))
79 			&& (0 == guid_compare (qof_entity_get_guid (ent),
80 					ref->ent_guid))
81 			&& (0 == safe_strcmp (ref->type, ent->e_type)))
82 		{
83 			QofCollection *temp_col;
84 			gchar cm_sa[GUID_ENCODING_LENGTH + 1];
85 
86 			temp_col = ref->param->param_getfcn (ent, ref->param);
87 			coll = qof_book_get_collection (partial_book,
88 				qof_collection_get_type (temp_col));
89 			guid_to_string_buff (ref->ref_guid, cm_sa);
90 			reference = qof_collection_lookup_entity (coll, ref->ref_guid);
91 			if (reference)
92 			{
93 				qof_collection_add_entity (temp_col, reference);
94 				qof_util_param_edit ((QofInstance *) ent, ref->param);
95 				qof_util_param_edit ((QofInstance *) reference, ref->param);
96 				if (collect_setter)
97 				{
98 					collect_setter (ent, temp_col);
99 				}
100 				qof_util_param_commit ((QofInstance *) ent, ref->param);
101 				qof_util_param_commit ((QofInstance *) reference, ref->param);
102 				qof_collection_destroy (temp_col);
103 			}
104 		}
105 		if (0 == safe_strcmp (ref->param->param_type, QOF_TYPE_CHOICE))
106 		{
107 			coll = qof_book_get_collection (partial_book, ref->type);
108 			reference = qof_collection_lookup_entity (coll, ref->ref_guid);
109 			qof_util_param_edit ((QofInstance *) ent, ref->param);
110 			qof_util_param_edit ((QofInstance *) reference, ref->param);
111 			if (choice_setter)
112 			{
113 				choice_setter (ent, reference);
114 			}
115 			qof_util_param_commit ((QofInstance *) ent, ref->param);
116 			qof_util_param_commit ((QofInstance *) reference, ref->param);
117 		}
118 		book_ref_list = g_list_next (book_ref_list);
119 	}
120 }
121 
122 static void
set_each_type(QofObject * obj,gpointer user_data)123 set_each_type (QofObject * obj, gpointer user_data)
124 {
125 	QofBook *book;
126 
127 	book = (QofBook *) user_data;
128 	qof_object_foreach (obj->e_type, book, entity_set_reference_cb, book);
129 }
130 
131 static QofEntityReference *
create_reference(QofEntity * ent,const QofParam * param)132 create_reference (QofEntity * ent, const QofParam * param)
133 {
134 	QofEntityReference *reference;
135 	QofEntity *ref_ent;
136 	const GUID *cm_guid;
137 	char cm_sa[GUID_ENCODING_LENGTH + 1];
138 	gchar *cm_string;
139 
140 	ref_ent = (QofEntity *) param->param_getfcn (ent, param);
141 	if (!ref_ent)
142 	{
143 		return NULL;
144 	}
145 	reference = g_new0 (QofEntityReference, 1);
146 	reference->type = ent->e_type;
147 	reference->ref_guid = g_new (GUID, 1);
148 	reference->ent_guid = &ent->guid;
149 	if (qof_object_is_choice (ent->e_type))
150 	{
151 		reference->choice_type = ref_ent->e_type;
152 	}
153 	reference->param = param;
154 	cm_guid = qof_entity_get_guid (ref_ent);
155 	guid_to_string_buff (cm_guid, cm_sa);
156 	cm_string = g_strdup (cm_sa);
157 	if (TRUE == string_to_guid (cm_string, reference->ref_guid))
158 	{
159 		g_free (cm_string);
160 		return reference;
161 	}
162 	g_free (cm_string);
163 	return NULL;
164 }
165 
166 QofEntityReference *
qof_entity_get_reference_from(QofEntity * ent,const QofParam * param)167 qof_entity_get_reference_from (QofEntity * ent, const QofParam * param)
168 {
169 	g_return_val_if_fail (param, NULL);
170 	param = qof_class_get_parameter (ent->e_type, param->param_name);
171 	g_return_val_if_fail (0 !=
172 		safe_strcmp (param->param_type, QOF_TYPE_COLLECT), NULL);
173 	return create_reference (ent, param);
174 }
175 
176 void
qof_book_set_references(QofBook * book)177 qof_book_set_references (QofBook * book)
178 {
179 	gboolean partial;
180 
181 	partial =
182 		(gboolean)
183 		GPOINTER_TO_INT (qof_book_get_data (book, PARTIAL_QOFBOOK));
184 	g_return_if_fail (partial);
185 	qof_object_foreach_type (set_each_type, book);
186 }
187