QOF  0.7.5
qofobject.c
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 
27 #include "config.h"
28 
29 #include <glib.h>
30 
31 #include "qof.h"
32 #include "qofobject-p.h"
33 
34 static QofLogModule log_module = QOF_MOD_OBJECT;
35 
36 static gboolean object_is_initialized = FALSE;
37 static GList *object_modules = NULL;
38 static GList *book_list = NULL;
39 static GHashTable *backend_data = NULL;
40 
41 gpointer
43 {
44  const QofObject *obj;
45 
46  if (!type_name)
47  return NULL;
48 
49  obj = qof_object_lookup (type_name);
50  if (!obj)
51  return NULL;
52 
53  if (obj->create)
54  return (obj->create (book));
55 
56  return NULL;
57 }
58 
59 void
61 {
62  GList *l;
63 
64  if (!book)
65  return;
66  ENTER (" ");
67  for (l = object_modules; l; l = l->next)
68  {
69  QofObject *obj = l->data;
70  if (obj->book_begin)
71  obj->book_begin (book);
72  }
73 
74  /* Remember this book for later */
75  book_list = g_list_prepend (book_list, book);
76  LEAVE (" ");
77 }
78 
79 void
80 qof_object_book_end (QofBook * book)
81 {
82  GList *l;
83 
84  if (!book)
85  return;
86  ENTER (" ");
87  for (l = object_modules; l; l = l->next)
88  {
89  QofObject *obj = l->data;
90  if (obj->book_end)
91  obj->book_end (book);
92  }
93 
94  /* Remove it from the list */
95  book_list = g_list_remove (book_list, book);
96  LEAVE (" ");
97 }
98 
99 gboolean
100 qof_object_is_dirty (QofBook * book)
101 {
102  GList *l;
103 
104  if (!book)
105  return FALSE;
106  for (l = object_modules; l; l = l->next)
107  {
108  QofObject *obj = l->data;
109  if (obj->is_dirty)
110  {
111  QofCollection *col;
112  col = qof_book_get_collection (book, obj->e_type);
113  if (obj->is_dirty (col))
114  return TRUE;
115  }
116  }
117  return FALSE;
118 }
119 
120 void
121 qof_object_mark_clean (QofBook * book)
122 {
123  GList *l;
124 
125  if (!book)
126  return;
127  for (l = object_modules; l; l = l->next)
128  {
129  QofObject *obj = l->data;
130  if (obj->mark_clean)
131  {
132  QofCollection *col;
133  col = qof_book_get_collection (book, obj->e_type);
134  (obj->mark_clean) (col);
135  }
136  }
137 }
138 
139 void
140 qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data)
141 {
142  GList *l;
143 
144  if (!cb)
145  return;
146 
147  for (l = object_modules; l; l = l->next)
148  {
149  QofObject *obj = l->data;
150  (cb) (obj, user_data);
151  }
152 }
153 
154 gboolean
155 qof_object_compliance (QofIdTypeConst type_name, gboolean warn)
156 {
157  const QofObject *obj;
158 
159  obj = qof_object_lookup (type_name);
160  if ((obj->create == NULL) || (obj->foreach == NULL))
161  {
162  if (warn)
163  {
164  PINFO (" Object type %s is not fully QOF compliant",
165  obj->e_type);
166  }
167  return FALSE;
168  }
169  return TRUE;
170 }
171 
172 
173 void
175  QofEntityForeachCB cb, gpointer user_data)
176 {
177  QofCollection *col;
178  const QofObject *obj;
179 
180  if (!book || !type_name)
181  {
182  return;
183  }
184  PINFO ("type=%s", type_name);
185 
186  obj = qof_object_lookup (type_name);
187  if (!obj)
188  {
189  PERR ("No object of type %s", type_name);
190  return;
191  }
192  col = qof_book_get_collection (book, obj->e_type);
193  if (!obj)
194  {
195  return;
196  }
197  if (obj->foreach)
198  {
199  obj->foreach (col, cb, user_data);
200  }
201  return;
202 }
203 
204 const gchar *
205 qof_object_printable (QofIdTypeConst type_name, gpointer obj)
206 {
207  const QofObject *b_obj;
208 
209  if (!type_name || !obj)
210  return NULL;
211 
212  b_obj = qof_object_lookup (type_name);
213  if (!b_obj)
214  return NULL;
215 
216  if (b_obj->printable)
217  return (b_obj->printable (obj));
218 
219  return NULL;
220 }
221 
222 const gchar *
224 {
225  const QofObject *obj;
226 
227  if (!type_name)
228  return NULL;
229 
230  obj = qof_object_lookup (type_name);
231  if (!obj)
232  return NULL;
233 
234  return (obj->type_label);
235 }
236 
237 static gboolean
238 clear_table (gpointer key __attribute__ ((unused)), gpointer value,
239  gpointer user_data __attribute__ ((unused)))
240 {
241  g_hash_table_destroy (value);
242  return TRUE;
243 }
244 
245 /* INITIALIZATION and PRIVATE FUNCTIONS */
246 
247 void
248 qof_object_initialize (void)
249 {
250  if (object_is_initialized)
251  return;
252  backend_data = g_hash_table_new (g_str_hash, g_str_equal);
253  object_is_initialized = TRUE;
254 }
255 
256 void
257 qof_object_shutdown (void)
258 {
259  g_return_if_fail (object_is_initialized == TRUE);
260 
261  g_hash_table_foreach_remove (backend_data, clear_table, NULL);
262  g_hash_table_destroy (backend_data);
263  backend_data = NULL;
264 
265  g_list_free (object_modules);
266  object_modules = NULL;
267  g_list_free (book_list);
268  book_list = NULL;
269  object_is_initialized = FALSE;
270 }
271 
272 /* Register new types of object objects.
273  * Return TRUE if successful,
274  * return FALSE if it fails, invalid arguments, or if the object
275  * already exists
276  */
277 gboolean
279 {
280  g_return_val_if_fail (object_is_initialized, FALSE);
281 
282  if (!object)
283  return FALSE;
284  g_return_val_if_fail (object->interface_version == QOF_OBJECT_VERSION,
285  FALSE);
286 
287  if (g_list_index (object_modules, (gpointer) object) == -1)
288  object_modules =
289  g_list_prepend (object_modules, (gpointer) object);
290  else
291  return FALSE;
292 
293  /* Now initialize all the known books */
294  if (object->book_begin && book_list)
295  {
296  GList *node;
297  for (node = book_list; node; node = node->next)
298  object->book_begin (node->data);
299  }
300 
301  return TRUE;
302 }
303 
304 const QofObject *
306 {
307  GList *qiter;
308  const QofObject *obj;
309 
310  g_return_val_if_fail (object_is_initialized, NULL);
311 
312  if (!name)
313  return NULL;
314 
315  for (qiter = object_modules; qiter; qiter = qiter->next)
316  {
317  obj = qiter->data;
318  if (!safe_strcmp (obj->e_type, name))
319  return obj;
320  }
321  return NULL;
322 }
323 
324 gboolean
326  const gchar * backend_name, gpointer be_data)
327 {
328  GHashTable *ht;
329  g_return_val_if_fail (object_is_initialized, FALSE);
330 
331  if (!type_name || *type_name == '\0' ||
332  !backend_name || *backend_name == '\0' || !be_data)
333  return FALSE;
334 
335  ht = g_hash_table_lookup (backend_data, backend_name);
336 
337  /* If it doesn't already exist, create a new table for this backend */
338  if (!ht)
339  {
340  ht = g_hash_table_new (g_str_hash, g_str_equal);
341  g_hash_table_insert (backend_data, (gchar *) backend_name, ht);
342  }
343 
344  /* Now insert the data */
345  g_hash_table_insert (ht, (gchar *) type_name, be_data);
346 
347  return TRUE;
348 }
349 
350 gpointer
351 qof_object_lookup_backend (QofIdTypeConst type_name,
352  const gchar * backend_name)
353 {
354  GHashTable *ht;
355 
356  if (!type_name || *type_name == '\0' ||
357  !backend_name || *backend_name == '\0')
358  return NULL;
359 
360  ht = g_hash_table_lookup (backend_data, (gchar *) backend_name);
361  if (!ht)
362  return NULL;
363 
364  return g_hash_table_lookup (ht, (gchar *) type_name);
365 }
366 
367 struct foreach_data
368 {
369  QofForeachBackendTypeCB cb;
370  gpointer user_data;
371 };
372 
373 static void
374 foreach_backend (gpointer key, gpointer be_item, gpointer arg)
375 {
376  gchar *data_type = key;
377  struct foreach_data *cb_data = arg;
378 
379  g_return_if_fail (key && be_item && arg);
380 
381  /* Call the callback for this data type */
382  (cb_data->cb) (data_type, be_item, cb_data->user_data);
383 }
384 
385 void
386 qof_object_foreach_backend (const gchar * backend_name,
387  QofForeachBackendTypeCB cb, gpointer user_data)
388 {
389  GHashTable *ht;
390  struct foreach_data cb_data;
391 
392  if (!backend_name || *backend_name == '\0' || !cb)
393  return;
394 
395  ht = g_hash_table_lookup (backend_data, (gchar *) backend_name);
396  if (!ht)
397  return;
398 
399  cb_data.cb = cb;
400  cb_data.user_data = user_data;
401 
402  g_hash_table_foreach (ht, foreach_backend, &cb_data);
403 }
404 
405 /* ========================= END OF FILE =================== */