Branch data Line data Source code
1 : : /********************************************************************\
2 : : * qofid.c -- QOF entity identifier implementation *
3 : : * Copyright (C) 2000 Dave Peticolas <dave@krondo.com> *
4 : : * Copyright (C) 2003 Linas Vepstas <linas@linas.org> *
5 : : * *
6 : : * This program is free software; you can redistribute it and/or *
7 : : * modify it under the terms of the GNU General Public License as *
8 : : * published by the Free Software Foundation; either version 2 of *
9 : : * the License, or (at your option) any later version. *
10 : : * *
11 : : * This program is distributed in the hope that it will be useful, *
12 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 : : * GNU General Public License for more details. *
15 : : * *
16 : : * You should have received a copy of the GNU General Public License*
17 : : * along with this program; if not, contact: *
18 : : * *
19 : : * Free Software Foundation Voice: +1-617-542-5942 *
20 : : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21 : : * Boston, MA 02110-1301, USA gnu@gnu.org *
22 : : * *
23 : : \********************************************************************/
24 : :
25 : : #include <glib.h>
26 : :
27 : : #include <config.h>
28 : : #include <string.h>
29 : :
30 : : #include "qof.h"
31 : : #include "qofid-p.h"
32 : : #include "qofinstance-p.h"
33 : :
34 : : static QofLogModule log_module = QOF_MOD_ENGINE;
35 : :
36 : : struct QofCollection_s
37 : : {
38 : : QofIdType e_type;
39 : : gboolean is_dirty;
40 : :
41 : : GHashTable * hash_of_entities;
42 : : gpointer data; /* place where object class can hang arbitrary data */
43 : : };
44 : :
45 : : /* =============================================================== */
46 : :
47 : : QofCollection *
48 : 5867 : qof_collection_new (QofIdType type)
49 : : {
50 : : QofCollection *col;
51 : 5867 : col = g_new0(QofCollection, 1);
52 : 5867 : col->e_type = static_cast<QofIdType>(CACHE_INSERT (type));
53 : 5867 : col->hash_of_entities = guid_hash_table_new();
54 : 5867 : col->data = NULL;
55 : 5867 : return col;
56 : : }
57 : :
58 : : void
59 : 4741 : qof_collection_destroy (QofCollection *col)
60 : : {
61 : 4741 : CACHE_REMOVE (col->e_type);
62 : 4741 : g_hash_table_destroy(col->hash_of_entities);
63 : 4741 : col->e_type = NULL;
64 : 4741 : col->hash_of_entities = NULL;
65 : 4741 : col->data = NULL; /** XXX there should be a destroy notifier for this */
66 : 4741 : g_free (col);
67 : 4741 : }
68 : :
69 : : /* =============================================================== */
70 : : /* getters */
71 : :
72 : : QofIdType
73 : 86990 : qof_collection_get_type (const QofCollection *col)
74 : : {
75 : 86990 : return col->e_type;
76 : : }
77 : :
78 : : /* =============================================================== */
79 : :
80 : : void
81 : 301104 : qof_collection_remove_entity (QofInstance *ent)
82 : : {
83 : : QofCollection *col;
84 : : const GncGUID *guid;
85 : :
86 : 301104 : if (!ent) return;
87 : 301104 : col = qof_instance_get_collection(ent);
88 : 301104 : if (!col) return;
89 : 196132 : guid = qof_instance_get_guid(ent);
90 : 196132 : g_hash_table_remove (col->hash_of_entities, guid);
91 : 196132 : qof_instance_set_collection(ent, NULL);
92 : : }
93 : :
94 : : void
95 : 191894 : qof_collection_insert_entity (QofCollection *col, QofInstance *ent)
96 : : {
97 : : const GncGUID *guid;
98 : :
99 : 191894 : if (!col || !ent) return;
100 : 141770 : guid = qof_instance_get_guid(ent);
101 : 141770 : if (guid_equal(guid, guid_null())) return;
102 : 141768 : g_return_if_fail (col->e_type == ent->e_type);
103 : 141768 : qof_collection_remove_entity (ent);
104 : 141768 : g_hash_table_insert (col->hash_of_entities, (gpointer)guid, ent);
105 : 141768 : qof_instance_set_collection(ent, col);
106 : : }
107 : :
108 : : gboolean
109 : 0 : qof_collection_add_entity (QofCollection *coll, QofInstance *ent)
110 : : {
111 : : QofInstance *e;
112 : : const GncGUID *guid;
113 : :
114 : 0 : e = NULL;
115 : 0 : if (!coll || !ent)
116 : : {
117 : 0 : return FALSE;
118 : : }
119 : 0 : guid = qof_instance_get_guid(ent);
120 : 0 : if (guid_equal(guid, guid_null()))
121 : : {
122 : 0 : return FALSE;
123 : : }
124 : 0 : g_return_val_if_fail (coll->e_type == ent->e_type, FALSE);
125 : 0 : e = qof_collection_lookup_entity(coll, guid);
126 : 0 : if ( e != NULL )
127 : : {
128 : 0 : return FALSE;
129 : : }
130 : 0 : g_hash_table_insert (coll->hash_of_entities, (gpointer)guid, ent);
131 : 0 : return TRUE;
132 : : }
133 : :
134 : :
135 : : static void
136 : 0 : collection_compare_cb (QofInstance *ent, gpointer user_data)
137 : : {
138 : : QofCollection *target;
139 : : QofInstance *e;
140 : : const GncGUID *guid;
141 : : gint value;
142 : :
143 : 0 : e = NULL;
144 : 0 : target = (QofCollection*)user_data;
145 : 0 : if (!target || !ent)
146 : : {
147 : 0 : return;
148 : : }
149 : 0 : value = *(gint*)qof_collection_get_data(target);
150 : 0 : if (value != 0)
151 : : {
152 : 0 : return;
153 : : }
154 : 0 : guid = qof_instance_get_guid(ent);
155 : 0 : if (guid_equal(guid, guid_null()))
156 : : {
157 : 0 : value = -1;
158 : 0 : qof_collection_set_data(target, &value);
159 : 0 : return;
160 : : }
161 : 0 : g_return_if_fail (target->e_type == ent->e_type);
162 : 0 : e = qof_collection_lookup_entity(target, guid);
163 : 0 : if ( e == NULL )
164 : : {
165 : 0 : value = 1;
166 : 0 : qof_collection_set_data(target, &value);
167 : 0 : return;
168 : : }
169 : 0 : value = 0;
170 : 0 : qof_collection_set_data(target, &value);
171 : : }
172 : :
173 : : gint
174 : 0 : qof_collection_compare (QofCollection *target, QofCollection *merge)
175 : : {
176 : : gint value;
177 : :
178 : 0 : value = 0;
179 : 0 : if (!target && !merge)
180 : : {
181 : 0 : return 0;
182 : : }
183 : 0 : if (target == merge)
184 : : {
185 : 0 : return 0;
186 : : }
187 : 0 : if (!target && merge)
188 : : {
189 : 0 : return -1;
190 : : }
191 : 0 : if (target && !merge)
192 : : {
193 : 0 : return 1;
194 : : }
195 : 0 : if (target->e_type != merge->e_type)
196 : : {
197 : 0 : return -1;
198 : : }
199 : 0 : qof_collection_set_data(target, &value);
200 : 0 : qof_collection_foreach(merge, collection_compare_cb, target);
201 : 0 : value = *(gint*)qof_collection_get_data(target);
202 : 0 : if (value == 0)
203 : : {
204 : 0 : qof_collection_set_data(merge, &value);
205 : 0 : qof_collection_foreach(target, collection_compare_cb, merge);
206 : 0 : value = *(gint*)qof_collection_get_data(merge);
207 : : }
208 : 0 : return value;
209 : : }
210 : :
211 : : QofInstance *
212 : 211792 : qof_collection_lookup_entity (const QofCollection *col, const GncGUID * guid)
213 : : {
214 : : QofInstance *ent;
215 : 211792 : g_return_val_if_fail (col, NULL);
216 : 211792 : if (guid == NULL) return NULL;
217 : 211792 : ent = static_cast<QofInstance*>(g_hash_table_lookup (col->hash_of_entities,
218 : : guid));
219 : 211792 : if (ent != NULL && qof_instance_get_destroying(ent)) return NULL;
220 : 211792 : return ent;
221 : : }
222 : :
223 : : QofCollection *
224 : 0 : qof_collection_from_glist (QofIdType type, const GList *glist)
225 : : {
226 : : QofCollection *coll;
227 : : QofInstance *ent;
228 : : const GList *list;
229 : :
230 : 0 : coll = qof_collection_new(type);
231 : 0 : for (list = glist; list != NULL; list = list->next)
232 : : {
233 : 0 : ent = QOF_INSTANCE(list->data);
234 : 0 : if (FALSE == qof_collection_add_entity(coll, ent))
235 : : {
236 : 0 : qof_collection_destroy(coll);
237 : 0 : return NULL;
238 : : }
239 : : }
240 : 0 : return coll;
241 : : }
242 : :
243 : : guint
244 : 33 : qof_collection_count (const QofCollection *col)
245 : : {
246 : : guint c;
247 : :
248 : 33 : c = g_hash_table_size(col->hash_of_entities);
249 : 33 : return c;
250 : : }
251 : :
252 : : /* =============================================================== */
253 : :
254 : : gboolean
255 : 2 : qof_collection_is_dirty (const QofCollection *col)
256 : : {
257 : 2 : return col ? col->is_dirty : FALSE;
258 : : }
259 : :
260 : : void
261 : 828 : qof_collection_mark_clean (QofCollection *col)
262 : : {
263 : 828 : if (col)
264 : : {
265 : 828 : col->is_dirty = FALSE;
266 : : }
267 : 828 : }
268 : :
269 : : void
270 : 108856 : qof_collection_mark_dirty (QofCollection *col)
271 : : {
272 : 108856 : if (col)
273 : : {
274 : 108852 : col->is_dirty = TRUE;
275 : : }
276 : 108856 : }
277 : :
278 : : void
279 : 0 : qof_collection_print_dirty (const QofCollection *col, gpointer dummy)
280 : : {
281 : 0 : if (col->is_dirty)
282 : 0 : printf("%s collection is dirty.\n", col->e_type);
283 : 0 : qof_collection_foreach(col, (QofInstanceForeachCB)qof_instance_print_dirty, NULL);
284 : 0 : }
285 : :
286 : : /* =============================================================== */
287 : :
288 : : gpointer
289 : 23623 : qof_collection_get_data (const QofCollection *col)
290 : : {
291 : 23623 : return col ? col->data : NULL;
292 : : }
293 : :
294 : : void
295 : 1617 : qof_collection_set_data (QofCollection *col, gpointer user_data)
296 : : {
297 : 1617 : if (col)
298 : : {
299 : 1617 : col->data = user_data;
300 : : }
301 : 1617 : }
302 : :
303 : : /* =============================================================== */
304 : :
305 : : void
306 : 5247 : qof_collection_foreach_sorted (const QofCollection *col, QofInstanceForeachCB cb_func,
307 : : gpointer user_data, GCompareFunc sort_fn)
308 : : {
309 : : GList *entries;
310 : :
311 : 5247 : g_return_if_fail (col);
312 : 5247 : g_return_if_fail (cb_func);
313 : :
314 : 5247 : PINFO("Hash Table size of %s before is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
315 : :
316 : 5247 : entries = g_hash_table_get_values (col->hash_of_entities);
317 : 5247 : if (sort_fn)
318 : 153 : entries = g_list_sort (entries, sort_fn);
319 : 5247 : g_list_foreach (entries, (GFunc)cb_func, user_data);
320 : 5247 : g_list_free (entries);
321 : :
322 : 5247 : PINFO("Hash Table size of %s after is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
323 : : }
324 : :
325 : : void
326 : 5094 : qof_collection_foreach (const QofCollection *col, QofInstanceForeachCB cb_func,
327 : : gpointer user_data)
328 : : {
329 : 5094 : qof_collection_foreach_sorted (col, cb_func, user_data, nullptr);
330 : 5094 : }
331 : : /* =============================================================== */
|