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