GnuCash  4.8a-132-gcdaeb421d+
qofobject.cpp
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 = NULL;
36 static GList *book_list = NULL;
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 #ifdef __cplusplus
44 extern "C"
45 {
46 #endif
47 
48 gboolean get_object_is_initialized( void );
49 GList* get_object_modules( void );
50 GList* get_book_list( void );
51 
52 #ifdef __cplusplus
53 }
54 #endif
55 
56 gboolean
57 get_object_is_initialized( void )
58 {
59  return object_is_initialized;
60 }
61 
62 GList*
63 get_object_modules( void )
64 {
65  return object_modules;
66 }
67 
68 GList*
69 get_book_list( void )
70 {
71  return book_list;
72 }
73 
74 /*********/
75 
76 gpointer
77 qof_object_new_instance (QofIdTypeConst type_name, QofBook *book)
78 {
79  const QofObject *obj;
80 
81  if (!type_name) return NULL;
82 
83  obj = qof_object_lookup (type_name);
84  if (!obj) return NULL;
85 
86  if (obj->create)
87  return (obj->create (book));
88 
89  return NULL;
90 }
91 
92 void qof_object_book_begin (QofBook *book)
93 {
94  GList *l;
95 
96  if (!book) return;
97  ENTER (" ");
98  for (l = object_modules; l; l = l->next)
99  {
100  QofObject *obj = static_cast<QofObject*>(l->data);
101  if (obj->book_begin)
102  obj->book_begin (book);
103  }
104 
105  /* Remember this book for later */
106  book_list = g_list_prepend (book_list, book);
107  LEAVE (" ");
108 }
109 
110 void qof_object_book_end (QofBook *book)
111 {
112  GList *l;
113 
114  if (!book) return;
115  ENTER (" ");
116  for (l = object_modules; l; l = l->next)
117  {
118  QofObject *obj = static_cast<QofObject*>(l->data);
119  if (obj->book_end)
120  obj->book_end (book);
121  }
122 
123  /* Remove it from the list */
124  book_list = g_list_remove (book_list, book);
125  LEAVE (" ");
126 }
127 
128 gboolean
129 qof_object_is_dirty (const QofBook *book)
130 {
131  GList *l;
132 
133  if (!book) return FALSE;
134  for (l = object_modules; l; l = l->next)
135  {
136  QofObject *obj = static_cast<QofObject*>(l->data);
137  if (obj->is_dirty)
138  {
139  QofCollection *col;
140  col = qof_book_get_collection (book, obj->e_type);
141  if (obj->is_dirty (col)) return TRUE;
142  }
143  }
144  return FALSE;
145 }
146 
147 void
148 qof_object_mark_clean (QofBook *book)
149 {
150  GList *l;
151 
152  if (!book) return;
153  for (l = object_modules; l; l = l->next)
154  {
155  QofObject *obj = static_cast<QofObject*>(l->data);
156  if (obj->mark_clean)
157  {
158  QofCollection *col;
159  col = qof_book_get_collection (book, obj->e_type);
160  (obj->mark_clean) (col);
161  }
162  }
163 }
164 
165 void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data)
166 {
167  GList *l;
168 
169  if (!cb) return;
170 
171  for (l = object_modules; l; l = l->next)
172  {
173  QofObject *obj = static_cast<QofObject*>(l->data);
174  (cb) (obj, user_data);
175  }
176 }
177 
178 gboolean
179 qof_object_compliance (QofIdTypeConst type_name, gboolean warn)
180 {
181  const QofObject *obj;
182 
183  obj = qof_object_lookup(type_name);
184  if ((obj->create == NULL) || (obj->foreach == NULL))
185  {
186  if (warn)
187  {
188  PINFO (" Object type %s is not fully QOF compliant", obj->e_type);
189  }
190  return FALSE;
191  }
192  return TRUE;
193 }
194 
195 
196 void
197 qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
198  QofInstanceForeachCB cb, gpointer user_data)
199 {
200  QofCollection *col;
201  const QofObject *obj;
202 
203  if (!book || !type_name)
204  {
205  return;
206  }
207  PINFO ("type=%s", type_name);
208 
209  obj = qof_object_lookup (type_name);
210  if (!obj)
211  {
212  PERR ("No object of type %s", type_name);
213  return;
214  }
215  col = qof_book_get_collection (book, obj->e_type);
216  if (!obj)
217  {
218  return;
219  }
220  if (obj->foreach)
221  {
222  obj->foreach (col, cb, user_data);
223  }
224  return;
225 }
226 
227 static void
228 do_prepend (QofInstance *qof_p, gpointer list_p)
229 {
230  GList **list = static_cast<GList**>(list_p);
231  *list = g_list_prepend(*list, qof_p);
232 }
233 
234 void
235 qof_object_foreach_sorted (QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
236 {
237  GList *list = NULL;
238  GList *iter;
239 
240  qof_object_foreach(type_name, book, do_prepend, &list);
241 
242  list = g_list_sort(list, qof_instance_guid_compare);
243 
244  for (iter = list; iter; iter = iter->next)
245  {
246  cb(static_cast<QofInstance*>(iter->data), user_data);
247  }
248 
249  g_list_free(list);
250 
251  // FIXME: Apparently this is a memory leak, as this g_list_free doesn't
252  // free all of the allocated memory of g_list_append in do_append(). Why?!?
253  // Does g_list_sort have special side-effects on the memory of the list?
254  // Subsequently, I've changed the g_list_append into g_list_prepend, but
255  // solely for performance reasons. To my surprise, this also makes the
256  // dubious memory leak go away. But again why?!?
257 }
258 
259 const char *
260 qof_object_printable (QofIdTypeConst type_name, gpointer obj)
261 {
262  const QofObject *b_obj;
263 
264  if (!type_name || !obj) return NULL;
265 
266  b_obj = qof_object_lookup (type_name);
267  if (!b_obj) return NULL;
268 
269  if (b_obj->printable)
270  return (b_obj->printable (obj));
271 
272  return NULL;
273 }
274 
276 {
277  const QofObject *obj;
278 
279  if (!type_name) return NULL;
280 
281  obj = qof_object_lookup (type_name);
282  if (!obj) return NULL;
283 
284  return (obj->type_label);
285 }
286 
287 static gboolean clear_table (gpointer key, gpointer value, gpointer user_data)
288 {
289  g_hash_table_destroy (static_cast<GHashTable*>(value));
290  return TRUE;
291 }
292 
293 /* INITIALIZATION and PRIVATE FUNCTIONS */
294 
295 void qof_object_initialize (void)
296 {
297  if (object_is_initialized) return;
298  object_is_initialized = TRUE;
299 }
300 
301 void qof_object_shutdown (void)
302 {
303  g_return_if_fail (object_is_initialized == TRUE);
304 
305  g_list_free (object_modules);
306  object_modules = NULL;
307  g_list_free (book_list);
308  book_list = NULL;
309  object_is_initialized = FALSE;
310 }
311 
312 /* Register new types of object objects.
313  * Return TRUE if successful,
314  * return FALSE if it fails, invalid arguments, or if the object
315  * already exists
316  */
317 gboolean qof_object_register (const QofObject *object)
318 {
319  g_return_val_if_fail (object_is_initialized, FALSE);
320 
321  if (!object) return FALSE;
322  g_return_val_if_fail (object->interface_version == QOF_OBJECT_VERSION, FALSE);
323 
324  if (g_list_index (object_modules, (gpointer)object) == -1)
325  object_modules = g_list_prepend (object_modules, (gpointer)object);
326  else
327  return FALSE;
328 
329  /* Now initialize all the known books */
330  if (object->book_begin && book_list)
331  {
332  GList *node;
333  for (node = book_list; node; node = node->next)
334  object->book_begin (static_cast<QofBook*>(node->data));
335  }
336 
337  return TRUE;
338 }
339 
340 const QofObject * qof_object_lookup (QofIdTypeConst name)
341 {
342  GList *iter;
343  const QofObject *obj;
344 
345  g_return_val_if_fail (object_is_initialized, NULL);
346 
347  if (!name) return NULL;
348 
349  for (iter = object_modules; iter; iter = iter->next)
350  {
351  obj = static_cast<QofObject*>(iter->data);
352  if (!g_strcmp0 (obj->e_type, name))
353  return obj;
354  }
355  return NULL;
356 }
357 
358 /* ========================= END OF FILE =================== */
const char * qof_object_get_type_label(QofIdTypeConst type_name)
Get the printable label for a type.
Definition: qofobject.cpp:275
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
void qof_object_book_begin(QofBook *book)
To be called from within the book.
Definition: qofobject.cpp:92
const gchar * QofIdTypeConst
QofIdTypeConst declaration.
Definition: qofid.h:87
gboolean qof_object_compliance(QofIdTypeConst type_name, gboolean warn)
check an object can be created and supports iteration
Definition: qofobject.cpp:179
void(* QofInstanceForeachCB)(QofInstance *, gpointer user_data)
Callback type for qof_collection_foreach.
Definition: qofid.h:146
#define QOF_OBJECT_VERSION
Defines the version of the core object object registration interface.
Definition: qofobject.h:64
#define PERR(format, args...)
Log a serious error.
Definition: qoflog.h:244
#define ENTER(format, args...)
Print a function entry debugging message.
Definition: qoflog.h:272
the Core Object Registration/Lookup Private Interface
void qof_object_foreach_type(QofForeachTypeCB cb, gpointer user_data)
Invoke the callback &#39;cb&#39; on every object class definition.
Definition: qofobject.cpp:165
void qof_object_foreach_sorted(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
Invoke callback &#39;cb&#39; on each instance in guid orted order.
Definition: qofobject.cpp:235
const QofObject * qof_object_lookup(QofIdTypeConst name)
Lookup an object definition.
Definition: qofobject.cpp:340
void qof_object_foreach(QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
Invoke the callback &#39;cb&#39; on every instance ov a particular object type.
Definition: qofobject.cpp:197
gpointer qof_object_new_instance(QofIdTypeConst type_name, QofBook *book)
Create an instance of the indicated type, returning a pointer to that instance.
Definition: qofobject.cpp:77
gint qof_instance_guid_compare(gconstpointer ptr1, gconstpointer ptr2)
Compare the GncGUID values of two instances.
const char * qof_object_printable(QofIdTypeConst type_name, gpointer obj)
Definition: qofobject.cpp:260
#define LEAVE(format, args...)
Print a function exit debugging message.
Definition: qoflog.h:282
QofCollection * qof_book_get_collection(const QofBook *book, QofIdType entity_type)
Return The table of entities of the given type.
Definition: qofbook.cpp:604
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
Definition: qofobject.cpp:317