Line data Source code
1 : /********************************************************************\
2 : * qofobject.c -- the Core Object Registration/Lookup Interface *
3 : * This program is free software; you can redistribute it and/or *
4 : * modify it under the terms of the GNU General Public License as *
5 : * published by the Free Software Foundation; either version 2 of *
6 : * the License, or (at your option) any later version. *
7 : * *
8 : * This program is distributed in the hope that it will be useful, *
9 : * but WITHOUT ANY WARRANTY; without even the implied warranty of *
10 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
11 : * GNU General Public License for more details. *
12 : * *
13 : * You should have received a copy of the GNU General Public License*
14 : * along with this program; if not, contact: *
15 : * *
16 : * Free Software Foundation Voice: +1-617-542-5942 *
17 : * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
18 : * Boston, MA 02110-1301, USA gnu@gnu.org *
19 : * *
20 : \********************************************************************/
21 : /*
22 : * qofobject.c -- the Core Object Object Registry
23 : * Copyright (C) 2001 Derek Atkins
24 : * Author: Derek Atkins <warlord@MIT.EDU>
25 : */
26 : #include <config.h>
27 : #include <glib.h>
28 :
29 : #include "qof.h"
30 : #include "qofobject-p.h"
31 :
32 : static QofLogModule log_module = QOF_MOD_OBJECT;
33 :
34 : static gboolean object_is_initialized = FALSE;
35 : static GList *object_modules = nullptr;
36 : static GList *book_list = nullptr;
37 :
38 : /*
39 : * These getters are used in tests to reach static vars from outside
40 : * They should be removed when no longer needed
41 : */
42 :
43 : extern "C"
44 : {
45 :
46 : GList* get_object_modules( void );
47 : GList* get_book_list( void );
48 : }
49 :
50 : GList*
51 30 : get_object_modules( void )
52 : {
53 30 : return object_modules;
54 : }
55 :
56 : GList*
57 12 : get_book_list( void )
58 : {
59 12 : return book_list;
60 : }
61 :
62 : /*********/
63 :
64 : gpointer
65 4 : qof_object_new_instance (QofIdTypeConst type_name, QofBook *book)
66 : {
67 : const QofObject *obj;
68 :
69 4 : if (!type_name) return nullptr;
70 :
71 3 : obj = qof_object_lookup (type_name);
72 3 : if (!obj) return nullptr;
73 :
74 2 : if (obj->create)
75 1 : return (obj->create (book));
76 :
77 1 : return nullptr;
78 : }
79 :
80 640 : void qof_object_book_begin (QofBook *book)
81 : {
82 : GList *l;
83 :
84 640 : if (!book) return;
85 640 : ENTER (" ");
86 8139 : for (l = object_modules; l; l = l->next)
87 : {
88 7499 : QofObject *obj = static_cast<QofObject*>(l->data);
89 7499 : if (obj->book_begin)
90 1979 : obj->book_begin (book);
91 : }
92 :
93 : /* Remember this book for later */
94 640 : book_list = g_list_prepend (book_list, book);
95 640 : LEAVE (" ");
96 : }
97 :
98 499 : void qof_object_book_end (QofBook *book)
99 : {
100 : GList *l;
101 :
102 499 : if (!book) return;
103 499 : ENTER (" ");
104 5080 : for (l = object_modules; l; l = l->next)
105 : {
106 4581 : QofObject *obj = static_cast<QofObject*>(l->data);
107 4581 : if (obj->book_end)
108 3055 : obj->book_end (book);
109 : }
110 :
111 : /* Remove it from the list */
112 499 : book_list = g_list_remove (book_list, book);
113 499 : LEAVE (" ");
114 : }
115 :
116 : gboolean
117 4 : qof_object_is_dirty (const QofBook *book)
118 : {
119 : GList *l;
120 :
121 4 : if (!book) return FALSE;
122 6 : for (l = object_modules; l; l = l->next)
123 : {
124 4 : QofObject *obj = static_cast<QofObject*>(l->data);
125 4 : if (obj->is_dirty)
126 : {
127 : QofCollection *col;
128 4 : col = qof_book_get_collection (book, obj->e_type);
129 4 : if (obj->is_dirty (col)) return TRUE;
130 : }
131 : }
132 2 : return FALSE;
133 : }
134 :
135 : void
136 2 : qof_object_mark_clean (QofBook *book)
137 : {
138 : GList *l;
139 :
140 2 : if (!book) return;
141 5 : for (l = object_modules; l; l = l->next)
142 : {
143 3 : QofObject *obj = static_cast<QofObject*>(l->data);
144 3 : if (obj->mark_clean)
145 : {
146 : QofCollection *col;
147 3 : col = qof_book_get_collection (book, obj->e_type);
148 3 : (obj->mark_clean) (col);
149 : }
150 : }
151 : }
152 :
153 7 : void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data)
154 : {
155 : GList *l;
156 :
157 7 : if (!cb) return;
158 :
159 25 : for (l = object_modules; l; l = l->next)
160 : {
161 18 : QofObject *obj = static_cast<QofObject*>(l->data);
162 18 : (cb) (obj, user_data);
163 : }
164 : }
165 :
166 : gboolean
167 8 : qof_object_compliance (QofIdTypeConst type_name, gboolean warn)
168 : {
169 : const QofObject *obj;
170 :
171 8 : obj = qof_object_lookup(type_name);
172 8 : if ((obj->create == nullptr) || (obj->foreach == nullptr))
173 : {
174 6 : if (warn)
175 : {
176 3 : PINFO (" Object type %s is not fully QOF compliant", obj->e_type);
177 : }
178 6 : return FALSE;
179 : }
180 2 : return TRUE;
181 : }
182 :
183 :
184 : void
185 690 : qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
186 : QofInstanceForeachCB cb, gpointer user_data)
187 : {
188 : QofCollection *col;
189 : const QofObject *obj;
190 :
191 690 : if (!book || !type_name)
192 : {
193 6 : return;
194 : }
195 684 : PINFO ("type=%s", type_name);
196 :
197 684 : obj = qof_object_lookup (type_name);
198 684 : if (!obj)
199 : {
200 0 : PERR ("No object of type %s", type_name);
201 0 : return;
202 : }
203 684 : col = qof_book_get_collection (book, obj->e_type);
204 684 : if (!col)
205 : {
206 0 : return;
207 : }
208 684 : if (obj->foreach)
209 : {
210 684 : obj->foreach (col, cb, user_data);
211 : }
212 684 : return;
213 : }
214 :
215 : static void
216 6 : do_prepend (QofInstance *qof_p, gpointer list_p)
217 : {
218 6 : GList **list = static_cast<GList**>(list_p);
219 6 : *list = g_list_prepend(*list, qof_p);
220 6 : }
221 :
222 : void
223 37 : qof_object_foreach_sorted (QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
224 : {
225 37 : GList *list = nullptr;
226 : GList *iter;
227 :
228 37 : qof_object_foreach(type_name, book, do_prepend, &list);
229 :
230 37 : list = g_list_sort(list, qof_instance_guid_compare);
231 :
232 43 : for (iter = list; iter; iter = iter->next)
233 : {
234 6 : cb(static_cast<QofInstance*>(iter->data), user_data);
235 : }
236 :
237 37 : g_list_free(list);
238 :
239 : // FIXME: Apparently this is a memory leak, as this g_list_free doesn't
240 : // free all of the allocated memory of g_list_append in do_append(). Why?!?
241 : // Does g_list_sort have special side-effects on the memory of the list?
242 : // Subsequently, I've changed the g_list_append into g_list_prepend, but
243 : // solely for performance reasons. To my surprise, this also makes the
244 : // dubious memory leak go away. But again why?!?
245 37 : }
246 :
247 : const char *
248 13 : qof_object_printable (QofIdTypeConst type_name, gpointer obj)
249 : {
250 : const QofObject *b_obj;
251 :
252 13 : if (!type_name || !obj) return nullptr;
253 :
254 8 : b_obj = qof_object_lookup (type_name);
255 8 : if (!b_obj) return nullptr;
256 :
257 7 : if (b_obj->printable)
258 6 : return (b_obj->printable (obj));
259 :
260 1 : return nullptr;
261 : }
262 :
263 4 : const char * qof_object_get_type_label (QofIdTypeConst type_name)
264 : {
265 : const QofObject *obj;
266 :
267 4 : if (!type_name) return nullptr;
268 :
269 3 : obj = qof_object_lookup (type_name);
270 3 : if (!obj) return nullptr;
271 :
272 2 : return (obj->type_label);
273 : }
274 :
275 : /* INITIALIZATION and PRIVATE FUNCTIONS */
276 :
277 131 : void qof_object_initialize (void)
278 : {
279 131 : if (object_is_initialized) return;
280 122 : object_is_initialized = TRUE;
281 : }
282 :
283 56 : void qof_object_shutdown (void)
284 : {
285 56 : g_return_if_fail (object_is_initialized == TRUE);
286 :
287 56 : g_list_free (object_modules);
288 56 : object_modules = nullptr;
289 56 : g_list_free (book_list);
290 56 : book_list = nullptr;
291 56 : object_is_initialized = FALSE;
292 : }
293 :
294 : /* Register new types of object objects.
295 : * Return TRUE if successful,
296 : * return FALSE if it fails, invalid arguments, or if the object
297 : * already exists
298 : */
299 2141 : gboolean qof_object_register (const QofObject *object)
300 : {
301 2141 : g_return_val_if_fail (object_is_initialized, FALSE);
302 :
303 2141 : if (!object) return FALSE;
304 2139 : g_return_val_if_fail (object->interface_version == QOF_OBJECT_VERSION, FALSE);
305 :
306 2139 : if (g_list_index (object_modules, (gpointer)object) == -1)
307 2114 : object_modules = g_list_prepend (object_modules, (gpointer)object);
308 : else
309 25 : return FALSE;
310 :
311 : /* Now initialize all the known books */
312 2114 : if (object->book_begin && book_list)
313 : {
314 : GList *node;
315 74 : for (node = book_list; node; node = node->next)
316 40 : object->book_begin (static_cast<QofBook*>(node->data));
317 : }
318 :
319 2114 : return TRUE;
320 : }
321 :
322 715 : const QofObject * qof_object_lookup (QofIdTypeConst name)
323 : {
324 : GList *iter;
325 : const QofObject *obj;
326 :
327 715 : g_return_val_if_fail (object_is_initialized, nullptr);
328 :
329 715 : if (!name) return nullptr;
330 :
331 7231 : for (iter = object_modules; iter; iter = iter->next)
332 : {
333 7226 : obj = static_cast<QofObject*>(iter->data);
334 7226 : if (!g_strcmp0 (obj->e_type, name))
335 709 : return obj;
336 : }
337 5 : return nullptr;
338 : }
339 :
340 : /* ========================= END OF FILE =================== */
|