GnuCash  5.6-150-g038405b370+
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 = 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 get_object_modules( void )
52 {
53  return object_modules;
54 }
55 
56 GList*
57 get_book_list( void )
58 {
59  return book_list;
60 }
61 
62 /*********/
63 
64 gpointer
65 qof_object_new_instance (QofIdTypeConst type_name, QofBook *book)
66 {
67  const QofObject *obj;
68 
69  if (!type_name) return nullptr;
70 
71  obj = qof_object_lookup (type_name);
72  if (!obj) return nullptr;
73 
74  if (obj->create)
75  return (obj->create (book));
76 
77  return nullptr;
78 }
79 
80 void qof_object_book_begin (QofBook *book)
81 {
82  GList *l;
83 
84  if (!book) return;
85  ENTER (" ");
86  for (l = object_modules; l; l = l->next)
87  {
88  QofObject *obj = static_cast<QofObject*>(l->data);
89  if (obj->book_begin)
90  obj->book_begin (book);
91  }
92 
93  /* Remember this book for later */
94  book_list = g_list_prepend (book_list, book);
95  LEAVE (" ");
96 }
97 
98 void qof_object_book_end (QofBook *book)
99 {
100  GList *l;
101 
102  if (!book) return;
103  ENTER (" ");
104  for (l = object_modules; l; l = l->next)
105  {
106  QofObject *obj = static_cast<QofObject*>(l->data);
107  if (obj->book_end)
108  obj->book_end (book);
109  }
110 
111  /* Remove it from the list */
112  book_list = g_list_remove (book_list, book);
113  LEAVE (" ");
114 }
115 
116 gboolean
117 qof_object_is_dirty (const QofBook *book)
118 {
119  GList *l;
120 
121  if (!book) return FALSE;
122  for (l = object_modules; l; l = l->next)
123  {
124  QofObject *obj = static_cast<QofObject*>(l->data);
125  if (obj->is_dirty)
126  {
127  QofCollection *col;
128  col = qof_book_get_collection (book, obj->e_type);
129  if (obj->is_dirty (col)) return TRUE;
130  }
131  }
132  return FALSE;
133 }
134 
135 void
136 qof_object_mark_clean (QofBook *book)
137 {
138  GList *l;
139 
140  if (!book) return;
141  for (l = object_modules; l; l = l->next)
142  {
143  QofObject *obj = static_cast<QofObject*>(l->data);
144  if (obj->mark_clean)
145  {
146  QofCollection *col;
147  col = qof_book_get_collection (book, obj->e_type);
148  (obj->mark_clean) (col);
149  }
150  }
151 }
152 
153 void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data)
154 {
155  GList *l;
156 
157  if (!cb) return;
158 
159  for (l = object_modules; l; l = l->next)
160  {
161  QofObject *obj = static_cast<QofObject*>(l->data);
162  (cb) (obj, user_data);
163  }
164 }
165 
166 gboolean
167 qof_object_compliance (QofIdTypeConst type_name, gboolean warn)
168 {
169  const QofObject *obj;
170 
171  obj = qof_object_lookup(type_name);
172  if ((obj->create == nullptr) || (obj->foreach == nullptr))
173  {
174  if (warn)
175  {
176  PINFO (" Object type %s is not fully QOF compliant", obj->e_type);
177  }
178  return FALSE;
179  }
180  return TRUE;
181 }
182 
183 
184 void
185 qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
186  QofInstanceForeachCB cb, gpointer user_data)
187 {
188  QofCollection *col;
189  const QofObject *obj;
190 
191  if (!book || !type_name)
192  {
193  return;
194  }
195  PINFO ("type=%s", type_name);
196 
197  obj = qof_object_lookup (type_name);
198  if (!obj)
199  {
200  PERR ("No object of type %s", type_name);
201  return;
202  }
203  col = qof_book_get_collection (book, obj->e_type);
204  if (!obj)
205  {
206  return;
207  }
208  if (obj->foreach)
209  {
210  obj->foreach (col, cb, user_data);
211  }
212  return;
213 }
214 
215 static void
216 do_prepend (QofInstance *qof_p, gpointer list_p)
217 {
218  GList **list = static_cast<GList**>(list_p);
219  *list = g_list_prepend(*list, qof_p);
220 }
221 
222 void
223 qof_object_foreach_sorted (QofIdTypeConst type_name, QofBook *book, QofInstanceForeachCB cb, gpointer user_data)
224 {
225  GList *list = nullptr;
226  GList *iter;
227 
228  qof_object_foreach(type_name, book, do_prepend, &list);
229 
230  list = g_list_sort(list, qof_instance_guid_compare);
231 
232  for (iter = list; iter; iter = iter->next)
233  {
234  cb(static_cast<QofInstance*>(iter->data), user_data);
235  }
236 
237  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 }
246 
247 const char *
248 qof_object_printable (QofIdTypeConst type_name, gpointer obj)
249 {
250  const QofObject *b_obj;
251 
252  if (!type_name || !obj) return nullptr;
253 
254  b_obj = qof_object_lookup (type_name);
255  if (!b_obj) return nullptr;
256 
257  if (b_obj->printable)
258  return (b_obj->printable (obj));
259 
260  return nullptr;
261 }
262 
264 {
265  const QofObject *obj;
266 
267  if (!type_name) return nullptr;
268 
269  obj = qof_object_lookup (type_name);
270  if (!obj) return nullptr;
271 
272  return (obj->type_label);
273 }
274 
275 /* INITIALIZATION and PRIVATE FUNCTIONS */
276 
277 void qof_object_initialize (void)
278 {
279  if (object_is_initialized) return;
280  object_is_initialized = TRUE;
281 }
282 
283 void qof_object_shutdown (void)
284 {
285  g_return_if_fail (object_is_initialized == TRUE);
286 
287  g_list_free (object_modules);
288  object_modules = nullptr;
289  g_list_free (book_list);
290  book_list = nullptr;
291  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 gboolean qof_object_register (const QofObject *object)
300 {
301  g_return_val_if_fail (object_is_initialized, FALSE);
302 
303  if (!object) return FALSE;
304  g_return_val_if_fail (object->interface_version == QOF_OBJECT_VERSION, FALSE);
305 
306  if (g_list_index (object_modules, (gpointer)object) == -1)
307  object_modules = g_list_prepend (object_modules, (gpointer)object);
308  else
309  return FALSE;
310 
311  /* Now initialize all the known books */
312  if (object->book_begin && book_list)
313  {
314  GList *node;
315  for (node = book_list; node; node = node->next)
316  object->book_begin (static_cast<QofBook*>(node->data));
317  }
318 
319  return TRUE;
320 }
321 
322 const QofObject * qof_object_lookup (QofIdTypeConst name)
323 {
324  GList *iter;
325  const QofObject *obj;
326 
327  g_return_val_if_fail (object_is_initialized, nullptr);
328 
329  if (!name) return nullptr;
330 
331  for (iter = object_modules; iter; iter = iter->next)
332  {
333  obj = static_cast<QofObject*>(iter->data);
334  if (!g_strcmp0 (obj->e_type, name))
335  return obj;
336  }
337  return nullptr;
338 }
339 
340 /* ========================= END OF FILE =================== */
const char * qof_object_get_type_label(QofIdTypeConst type_name)
Get the printable label for a type.
Definition: qofobject.cpp:263
#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:80
const gchar * QofIdTypeConst
QofIdTypeConst declaration.
Definition: qofid.h:82
gboolean qof_object_compliance(QofIdTypeConst type_name, gboolean warn)
check an object can be created and supports iteration
Definition: qofobject.cpp:167
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:63
#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:153
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:223
const QofObject * qof_object_lookup(QofIdTypeConst name)
Lookup an object definition.
Definition: qofobject.cpp:322
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:185
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:65
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:248
#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:521
gboolean qof_object_register(const QofObject *object)
Register new types of object objects.
Definition: qofobject.cpp:299