00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "config.h"
00028
00029 #include <glib.h>
00030
00031 #include "qof.h"
00032 #include "qofobject-p.h"
00033
00034 static QofLogModule log_module = QOF_MOD_OBJECT;
00035
00036 static gboolean object_is_initialized = FALSE;
00037 static GList *object_modules = NULL;
00038 static GList *book_list = NULL;
00039 static GHashTable *backend_data = NULL;
00040
00041 gpointer
00042 qof_object_new_instance (QofIdTypeConst type_name, QofBook *book)
00043 {
00044 const QofObject *obj;
00045
00046 if (!type_name) return NULL;
00047
00048 obj = qof_object_lookup (type_name);
00049 if (!obj) return NULL;
00050
00051 if (obj->create)
00052 return (obj->create (book));
00053
00054 return NULL;
00055 }
00056
00057 void qof_object_book_begin (QofBook *book)
00058 {
00059 GList *l;
00060
00061 if (!book) return;
00062 ENTER (" ");
00063 for (l = object_modules; l; l = l->next) {
00064 QofObject *obj = l->data;
00065 if (obj->book_begin)
00066 obj->book_begin (book);
00067 }
00068
00069
00070 book_list = g_list_prepend (book_list, book);
00071 LEAVE (" ");
00072 }
00073
00074 void qof_object_book_end (QofBook *book)
00075 {
00076 GList *l;
00077
00078 if (!book) return;
00079 ENTER (" ");
00080 for (l = object_modules; l; l = l->next) {
00081 QofObject *obj = l->data;
00082 if (obj->book_end)
00083 obj->book_end (book);
00084 }
00085
00086
00087 book_list = g_list_remove (book_list, book);
00088 LEAVE (" ");
00089 }
00090
00091 gboolean
00092 qof_object_is_dirty (QofBook *book)
00093 {
00094 GList *l;
00095
00096 if (!book) return FALSE;
00097 for (l = object_modules; l; l = l->next)
00098 {
00099 QofObject *obj = l->data;
00100 if (obj->is_dirty)
00101 {
00102 QofCollection *col;
00103 col = qof_book_get_collection (book, obj->e_type);
00104 if (obj->is_dirty (col)) return TRUE;
00105 }
00106 }
00107 return FALSE;
00108 }
00109
00110 void
00111 qof_object_mark_clean (QofBook *book)
00112 {
00113 GList *l;
00114
00115 if (!book) return;
00116 for (l = object_modules; l; l = l->next)
00117 {
00118 QofObject *obj = l->data;
00119 if (obj->mark_clean)
00120 {
00121 QofCollection *col;
00122 col = qof_book_get_collection (book, obj->e_type);
00123 (obj->mark_clean) (col);
00124 }
00125 }
00126 }
00127
00128 void qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data)
00129 {
00130 GList *l;
00131
00132 if (!cb) return;
00133
00134 for (l = object_modules; l; l = l->next) {
00135 QofObject *obj = l->data;
00136 (cb) (obj, user_data);
00137 }
00138 }
00139
00140 gboolean
00141 qof_object_compliance (QofIdTypeConst type_name, gboolean warn)
00142 {
00143 const QofObject *obj;
00144
00145 obj = qof_object_lookup(type_name);
00146 if((obj->create == NULL)||(obj->foreach == NULL)){
00147 if(warn)
00148 {
00149 PINFO (" Object type %s is not fully QOF compliant", obj->e_type);
00150 }
00151 return FALSE;
00152 }
00153 return TRUE;
00154 }
00155
00156
00157 void
00158 qof_object_foreach (QofIdTypeConst type_name, QofBook *book,
00159 QofEntityForeachCB cb, gpointer user_data)
00160 {
00161 QofCollection *col;
00162 const QofObject *obj;
00163
00164 if (!book || !type_name) { return; }
00165 PINFO ("type=%s", type_name);
00166
00167 obj = qof_object_lookup (type_name);
00168 if (!obj)
00169 {
00170 PERR ("No object of type %s", type_name);
00171 return;
00172 }
00173 col = qof_book_get_collection (book, obj->e_type);
00174 if (!obj) { return; }
00175 if (obj->foreach)
00176 {
00177 obj->foreach (col, cb, user_data);
00178 }
00179 return;
00180 }
00181
00182 const char *
00183 qof_object_printable (QofIdTypeConst type_name, gpointer obj)
00184 {
00185 const QofObject *b_obj;
00186
00187 if (!type_name || !obj) return NULL;
00188
00189 b_obj = qof_object_lookup (type_name);
00190 if (!b_obj) return NULL;
00191
00192 if (b_obj->printable)
00193 return (b_obj->printable (obj));
00194
00195 return NULL;
00196 }
00197
00198 const char * qof_object_get_type_label (QofIdTypeConst type_name)
00199 {
00200 const QofObject *obj;
00201
00202 if (!type_name) return NULL;
00203
00204 obj = qof_object_lookup (type_name);
00205 if (!obj) return NULL;
00206
00207 return (obj->type_label);
00208 }
00209
00210 static gboolean clear_table (gpointer key, gpointer value, gpointer user_data)
00211 {
00212 g_hash_table_destroy (value);
00213 return TRUE;
00214 }
00215
00216
00217
00218 void qof_object_initialize (void)
00219 {
00220 if (object_is_initialized) return;
00221 backend_data = g_hash_table_new (g_str_hash, g_str_equal);
00222 object_is_initialized = TRUE;
00223 }
00224
00225 void qof_object_shutdown (void)
00226 {
00227 g_return_if_fail (object_is_initialized == TRUE);
00228
00229 g_hash_table_foreach_remove (backend_data, clear_table, NULL);
00230 g_hash_table_destroy (backend_data);
00231 backend_data = NULL;
00232
00233 g_list_free (object_modules);
00234 object_modules = NULL;
00235 g_list_free (book_list);
00236 book_list = NULL;
00237 object_is_initialized = FALSE;
00238 }
00239
00240
00241
00242
00243
00244
00245 gboolean qof_object_register (const QofObject *object)
00246 {
00247 g_return_val_if_fail (object_is_initialized, FALSE);
00248
00249 if (!object) return FALSE;
00250 g_return_val_if_fail (object->interface_version == QOF_OBJECT_VERSION, FALSE);
00251
00252 if (g_list_index (object_modules, (gpointer)object) == -1)
00253 object_modules = g_list_prepend (object_modules, (gpointer)object);
00254 else
00255 return FALSE;
00256
00257
00258 if (object->book_begin && book_list) {
00259 GList *node;
00260 for (node = book_list; node; node = node->next)
00261 object->book_begin (node->data);
00262 }
00263
00264 return TRUE;
00265 }
00266
00267 const QofObject * qof_object_lookup (QofIdTypeConst name)
00268 {
00269 GList *iter;
00270 const QofObject *obj;
00271
00272 g_return_val_if_fail (object_is_initialized, NULL);
00273
00274 if (!name) return NULL;
00275
00276 for (iter = object_modules; iter; iter = iter->next) {
00277 obj = iter->data;
00278 if (!safe_strcmp (obj->e_type, name))
00279 return obj;
00280 }
00281 return NULL;
00282 }
00283
00284 gboolean qof_object_register_backend (QofIdTypeConst type_name,
00285 const char *backend_name,
00286 gpointer be_data)
00287 {
00288 GHashTable *ht;
00289 g_return_val_if_fail (object_is_initialized, FALSE);
00290
00291 if (!type_name || *type_name == '\0' ||
00292 !backend_name || *backend_name == '\0' ||
00293 !be_data)
00294 return FALSE;
00295
00296 ht = g_hash_table_lookup (backend_data, backend_name);
00297
00298
00299 if (!ht) {
00300 ht = g_hash_table_new (g_str_hash, g_str_equal);
00301 g_hash_table_insert (backend_data, (char *)backend_name, ht);
00302 }
00303
00304
00305 g_hash_table_insert (ht, (char *)type_name, be_data);
00306
00307 return TRUE;
00308 }
00309
00310 gpointer qof_object_lookup_backend (QofIdTypeConst type_name,
00311 const char *backend_name)
00312 {
00313 GHashTable *ht;
00314
00315 if (!type_name || *type_name == '\0' ||
00316 !backend_name || *backend_name == '\0')
00317 return NULL;
00318
00319 ht = g_hash_table_lookup (backend_data, (char *)backend_name);
00320 if (!ht)
00321 return NULL;
00322
00323 return g_hash_table_lookup (ht, (char *)type_name);
00324 }
00325
00326 struct foreach_data {
00327 QofForeachBackendTypeCB cb;
00328 gpointer user_data;
00329 };
00330
00331 static void foreach_backend (gpointer key, gpointer be_item, gpointer arg)
00332 {
00333 char *data_type = key;
00334 struct foreach_data *cb_data = arg;
00335
00336 g_return_if_fail (key && be_item && arg);
00337
00338
00339 (cb_data->cb) (data_type, be_item, cb_data->user_data);
00340 }
00341
00342 void qof_object_foreach_backend (const char *backend_name,
00343 QofForeachBackendTypeCB cb,
00344 gpointer user_data)
00345 {
00346 GHashTable *ht;
00347 struct foreach_data cb_data;
00348
00349 if (!backend_name || *backend_name == '\0' || !cb)
00350 return;
00351
00352 ht = g_hash_table_lookup (backend_data, (char *)backend_name);
00353 if (!ht)
00354 return;
00355
00356 cb_data.cb = cb;
00357 cb_data.user_data = user_data;
00358
00359 g_hash_table_foreach (ht, foreach_backend, &cb_data);
00360 }
00361
00362