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