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 : 5982 : qof_collection_new (QofIdType type)
49 : : {
50 : : QofCollection *col;
51 : 5982 : col = g_new0(QofCollection, 1);
52 : 5982 : col->e_type = static_cast<QofIdType>(CACHE_INSERT (type));
53 : 5982 : col->is_dirty = FALSE;
54 : 5982 : col->hash_of_entities = guid_hash_table_new();
55 : 5982 : col->data = NULL;
56 : 5982 : return col;
57 : : }
58 : :
59 : : void
60 : 4819 : qof_collection_destroy (QofCollection *col)
61 : : {
62 : 4819 : CACHE_REMOVE (col->e_type);
63 : 4819 : g_hash_table_destroy(col->hash_of_entities);
64 : 4819 : col->e_type = NULL;
65 : 4819 : col->hash_of_entities = NULL;
66 : 4819 : col->data = NULL; /** XXX there should be a destroy notifier for this */
67 : 4819 : g_free (col);
68 : 4819 : }
69 : :
70 : : /* =============================================================== */
71 : : /* getters */
72 : :
73 : : QofIdType
74 : 84546 : qof_collection_get_type (const QofCollection *col)
75 : : {
76 : 84546 : return col->e_type;
77 : : }
78 : :
79 : : /* =============================================================== */
80 : :
81 : : void
82 : 295806 : qof_collection_remove_entity (QofInstance *ent)
83 : : {
84 : : QofCollection *col;
85 : : const GncGUID *guid;
86 : :
87 : 295806 : if (!ent) return;
88 : 295806 : col = qof_instance_get_collection(ent);
89 : 295806 : if (!col) return;
90 : 190806 : guid = qof_instance_get_guid(ent);
91 : 190806 : g_hash_table_remove (col->hash_of_entities, guid);
92 : 190806 : qof_instance_set_collection(ent, NULL);
93 : : }
94 : :
95 : : void
96 : 189494 : qof_collection_insert_entity (QofCollection *col, QofInstance *ent)
97 : : {
98 : : const GncGUID *guid;
99 : :
100 : 189494 : if (!col || !ent) return;
101 : 139370 : guid = qof_instance_get_guid(ent);
102 : 139370 : if (guid_equal(guid, guid_null())) return;
103 : 139365 : g_return_if_fail (col->e_type == ent->e_type);
104 : 139365 : qof_collection_remove_entity (ent);
105 : 139365 : g_hash_table_insert (col->hash_of_entities, (gpointer)guid, ent);
106 : 139365 : qof_instance_set_collection(ent, col);
107 : : }
108 : :
109 : : gboolean
110 : 18 : qof_collection_add_entity (QofCollection *coll, QofInstance *ent)
111 : : {
112 : : QofInstance *e;
113 : : const GncGUID *guid;
114 : :
115 : 18 : e = NULL;
116 : 18 : if (!coll || !ent)
117 : : {
118 : 3 : return FALSE;
119 : : }
120 : 15 : guid = qof_instance_get_guid(ent);
121 : 15 : if (guid_equal(guid, guid_null()))
122 : : {
123 : 1 : return FALSE;
124 : : }
125 : 14 : g_return_val_if_fail (coll->e_type == ent->e_type, FALSE);
126 : 13 : e = qof_collection_lookup_entity(coll, guid);
127 : 13 : if ( e != NULL )
128 : : {
129 : 1 : return FALSE;
130 : : }
131 : 12 : g_hash_table_insert (coll->hash_of_entities, (gpointer)guid, ent);
132 : 12 : return TRUE;
133 : : }
134 : :
135 : :
136 : : static void
137 : 14 : collection_compare_cb (QofInstance *ent, gpointer user_data)
138 : : {
139 : : QofCollection *target;
140 : : QofInstance *e;
141 : : const GncGUID *guid;
142 : : gint* value;
143 : :
144 : 14 : e = NULL;
145 : 14 : target = (QofCollection*)user_data;
146 : 14 : if (!target || !ent)
147 : : {
148 : 0 : return;
149 : : }
150 : 14 : value = (gint*)qof_collection_get_data(target);
151 : 14 : if (*value != 0)
152 : : {
153 : 7 : return;
154 : : }
155 : 7 : guid = qof_instance_get_guid(ent);
156 : 7 : if (guid_equal(guid, guid_null()))
157 : : {
158 : 2 : *value = -1;
159 : 2 : return;
160 : : }
161 : 5 : g_return_if_fail (target->e_type == ent->e_type);
162 : 5 : e = qof_collection_lookup_entity(target, guid);
163 : 5 : if ( e == NULL )
164 : : {
165 : 2 : *value = 1;
166 : 2 : return;
167 : : }
168 : 3 : *value = 0;
169 : : }
170 : :
171 : : gint
172 : 11 : qof_collection_compare (QofCollection *target, QofCollection *merge)
173 : : {
174 : : gint value;
175 : :
176 : 11 : value = 0;
177 : 11 : if (!target && !merge)
178 : : {
179 : 1 : return 0;
180 : : }
181 : 10 : if (target == merge)
182 : : {
183 : 1 : return 0;
184 : : }
185 : 9 : if (!target && merge)
186 : : {
187 : 1 : return -1;
188 : : }
189 : 8 : if (target && !merge)
190 : : {
191 : 1 : return 1;
192 : : }
193 : 7 : if (target->e_type != merge->e_type)
194 : : {
195 : 1 : return -1;
196 : : }
197 : 6 : qof_collection_set_data(target, &value);
198 : 6 : qof_collection_foreach(merge, collection_compare_cb, target);
199 : 6 : value = *(gint*)qof_collection_get_data(target);
200 : 6 : if (value == 0)
201 : : {
202 : 3 : qof_collection_set_data(merge, &value);
203 : 3 : qof_collection_foreach(target, collection_compare_cb, merge);
204 : 3 : value = *(gint*)qof_collection_get_data(merge);
205 : : }
206 : 6 : return value;
207 : : }
208 : :
209 : : QofInstance *
210 : 189854 : qof_collection_lookup_entity (const QofCollection *col, const GncGUID * guid)
211 : : {
212 : : QofInstance *ent;
213 : 189854 : g_return_val_if_fail (col, NULL);
214 : 189854 : if (guid == NULL) return NULL;
215 : 189854 : ent = static_cast<QofInstance*>(g_hash_table_lookup (col->hash_of_entities,
216 : : guid));
217 : 189854 : if (ent != NULL && qof_instance_get_destroying(ent)) return NULL;
218 : 189854 : return ent;
219 : : }
220 : :
221 : : guint
222 : 16 : qof_collection_count (const QofCollection *col)
223 : : {
224 : : guint c;
225 : :
226 : 16 : c = g_hash_table_size(col->hash_of_entities);
227 : 16 : return c;
228 : : }
229 : :
230 : : /* =============================================================== */
231 : :
232 : : gboolean
233 : 5 : qof_collection_is_dirty (const QofCollection *col)
234 : : {
235 : 5 : return col ? col->is_dirty : FALSE;
236 : : }
237 : :
238 : : void
239 : 838 : qof_collection_mark_clean (QofCollection *col)
240 : : {
241 : 838 : if (col)
242 : : {
243 : 838 : col->is_dirty = FALSE;
244 : : }
245 : 838 : }
246 : :
247 : : void
248 : 106772 : qof_collection_mark_dirty (QofCollection *col)
249 : : {
250 : 106772 : if (col)
251 : : {
252 : 106768 : col->is_dirty = TRUE;
253 : : }
254 : 106772 : }
255 : :
256 : : void
257 : 2 : qof_collection_print_dirty (const QofCollection *col, gpointer dummy)
258 : : {
259 : 2 : if (col->is_dirty)
260 : 1 : printf("%s collection is dirty.\n", col->e_type);
261 : 2 : qof_collection_foreach(col, (QofInstanceForeachCB)qof_instance_print_dirty, NULL);
262 : 2 : }
263 : :
264 : : /* =============================================================== */
265 : :
266 : : gpointer
267 : 6561 : qof_collection_get_data (const QofCollection *col)
268 : : {
269 : 6561 : return col ? col->data : NULL;
270 : : }
271 : :
272 : : void
273 : 1639 : qof_collection_set_data (QofCollection *col, gpointer user_data)
274 : : {
275 : 1639 : if (col)
276 : : {
277 : 1639 : col->data = user_data;
278 : : }
279 : 1639 : }
280 : :
281 : : /* =============================================================== */
282 : :
283 : : void
284 : 3792 : qof_collection_foreach_sorted (const QofCollection *col, QofInstanceForeachCB cb_func,
285 : : gpointer user_data, GCompareFunc sort_fn)
286 : : {
287 : : GList *entries;
288 : :
289 : 3792 : g_return_if_fail (col);
290 : 3792 : g_return_if_fail (cb_func);
291 : :
292 : 3792 : PINFO("Hash Table size of %s before is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
293 : :
294 : 3792 : entries = g_hash_table_get_values (col->hash_of_entities);
295 : 3792 : if (sort_fn)
296 : 155 : entries = g_list_sort (entries, sort_fn);
297 : 3792 : g_list_foreach (entries, (GFunc)cb_func, user_data);
298 : 3792 : g_list_free (entries);
299 : :
300 : 3792 : PINFO("Hash Table size of %s after is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
301 : : }
302 : :
303 : : void
304 : 3637 : qof_collection_foreach (const QofCollection *col, QofInstanceForeachCB cb_func,
305 : : gpointer user_data)
306 : : {
307 : 3637 : qof_collection_foreach_sorted (col, cb_func, user_data, nullptr);
308 : 3637 : }
309 : : /* =============================================================== */
|