Branch data 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 : 568 : void qof_object_book_begin (QofBook *book)
81 : : {
82 : : GList *l;
83 : :
84 : 568 : if (!book) return;
85 : 568 : ENTER (" ");
86 : 6883 : for (l = object_modules; l; l = l->next)
87 : : {
88 : 6315 : QofObject *obj = static_cast<QofObject*>(l->data);
89 : 6315 : if (obj->book_begin)
90 : 1679 : obj->book_begin (book);
91 : : }
92 : :
93 : : /* Remember this book for later */
94 : 568 : book_list = g_list_prepend (book_list, book);
95 : 568 : LEAVE (" ");
96 : : }
97 : :
98 : 457 : void qof_object_book_end (QofBook *book)
99 : : {
100 : : GList *l;
101 : :
102 : 457 : if (!book) return;
103 : 457 : ENTER (" ");
104 : 4410 : for (l = object_modules; l; l = l->next)
105 : : {
106 : 3953 : QofObject *obj = static_cast<QofObject*>(l->data);
107 : 3953 : if (obj->book_end)
108 : 2633 : obj->book_end (book);
109 : : }
110 : :
111 : : /* Remove it from the list */
112 : 457 : book_list = g_list_remove (book_list, book);
113 : 457 : 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 : 2408 : qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
186 : : QofInstanceForeachCB cb, gpointer user_data)
187 : : {
188 : : QofCollection *col;
189 : : const QofObject *obj;
190 : :
191 : 2408 : if (!book || !type_name)
192 : : {
193 : 6 : return;
194 : : }
195 : 2402 : PINFO ("type=%s", type_name);
196 : :
197 : 2402 : obj = qof_object_lookup (type_name);
198 : 2402 : if (!obj)
199 : : {
200 : 0 : PERR ("No object of type %s", type_name);
201 : 0 : return;
202 : : }
203 : 2402 : col = qof_book_get_collection (book, obj->e_type);
204 : 2402 : if (!obj)
205 : : {
206 : 0 : return;
207 : : }
208 : 2402 : if (obj->foreach)
209 : : {
210 : 2402 : obj->foreach (col, cb, user_data);
211 : : }
212 : 2402 : return;
213 : : }
214 : :
215 : : static void
216 : 8 : do_prepend (QofInstance *qof_p, gpointer list_p)
217 : : {
218 : 8 : GList **list = static_cast<GList**>(list_p);
219 : 8 : *list = g_list_prepend(*list, qof_p);
220 : 8 : }
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 : 45 : for (iter = list; iter; iter = iter->next)
233 : : {
234 : 8 : 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 : 129 : void qof_object_initialize (void)
278 : : {
279 : 129 : if (object_is_initialized) return;
280 : 120 : object_is_initialized = TRUE;
281 : : }
282 : :
283 : 55 : void qof_object_shutdown (void)
284 : : {
285 : 55 : g_return_if_fail (object_is_initialized == TRUE);
286 : :
287 : 55 : g_list_free (object_modules);
288 : 55 : object_modules = nullptr;
289 : 55 : g_list_free (book_list);
290 : 55 : book_list = nullptr;
291 : 55 : 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 : 2093 : gboolean qof_object_register (const QofObject *object)
300 : : {
301 : 2093 : g_return_val_if_fail (object_is_initialized, FALSE);
302 : :
303 : 2093 : if (!object) return FALSE;
304 : 2091 : g_return_val_if_fail (object->interface_version == QOF_OBJECT_VERSION, FALSE);
305 : :
306 : 2091 : if (g_list_index (object_modules, (gpointer)object) == -1)
307 : 2066 : object_modules = g_list_prepend (object_modules, (gpointer)object);
308 : : else
309 : 25 : return FALSE;
310 : :
311 : : /* Now initialize all the known books */
312 : 2066 : if (object->book_begin && book_list)
313 : : {
314 : : GList *node;
315 : 77 : for (node = book_list; node; node = node->next)
316 : 42 : object->book_begin (static_cast<QofBook*>(node->data));
317 : : }
318 : :
319 : 2066 : return TRUE;
320 : : }
321 : :
322 : 2433 : const QofObject * qof_object_lookup (QofIdTypeConst name)
323 : : {
324 : : GList *iter;
325 : : const QofObject *obj;
326 : :
327 : 2433 : g_return_val_if_fail (object_is_initialized, nullptr);
328 : :
329 : 2433 : if (!name) return nullptr;
330 : :
331 : 33071 : for (iter = object_modules; iter; iter = iter->next)
332 : : {
333 : 33066 : obj = static_cast<QofObject*>(iter->data);
334 : 33066 : if (!g_strcmp0 (obj->e_type, name))
335 : 2427 : return obj;
336 : : }
337 : 5 : return nullptr;
338 : : }
339 : :
340 : : /* ========================= END OF FILE =================== */
|