QOF
0.7.5
|
00001 /********************************************************************\ 00002 * qofobject.c -- the Core Object Registration/Lookup Interface * 00003 * This program is free software; you can redistribute it and/or * 00004 * modify it under the terms of the GNU General Public License as * 00005 * published by the Free Software Foundation; either version 2 of * 00006 * the License, or (at your option) any later version. * 00007 * * 00008 * This program is distributed in the hope that it will be useful, * 00009 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00011 * GNU General Public License for more details. * 00012 * * 00013 * You should have received a copy of the GNU General Public License* 00014 * along with this program; if not, contact: * 00015 * * 00016 * Free Software Foundation Voice: +1-617-542-5942 * 00017 * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 * 00018 * Boston, MA 02110-1301, USA gnu@gnu.org * 00019 * * 00020 \********************************************************************/ 00021 /* 00022 * qofobject.c -- the Core Object Object Registry 00023 * Copyright (C) 2001 Derek Atkins 00024 * Author: Derek Atkins <warlord@MIT.EDU> 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) 00047 return NULL; 00048 00049 obj = qof_object_lookup (type_name); 00050 if (!obj) 00051 return NULL; 00052 00053 if (obj->create) 00054 return (obj->create (book)); 00055 00056 return NULL; 00057 } 00058 00059 void 00060 qof_object_book_begin (QofBook * book) 00061 { 00062 GList *l; 00063 00064 if (!book) 00065 return; 00066 ENTER (" "); 00067 for (l = object_modules; l; l = l->next) 00068 { 00069 QofObject *obj = l->data; 00070 if (obj->book_begin) 00071 obj->book_begin (book); 00072 } 00073 00074 /* Remember this book for later */ 00075 book_list = g_list_prepend (book_list, book); 00076 LEAVE (" "); 00077 } 00078 00079 void 00080 qof_object_book_end (QofBook * book) 00081 { 00082 GList *l; 00083 00084 if (!book) 00085 return; 00086 ENTER (" "); 00087 for (l = object_modules; l; l = l->next) 00088 { 00089 QofObject *obj = l->data; 00090 if (obj->book_end) 00091 obj->book_end (book); 00092 } 00093 00094 /* Remove it from the list */ 00095 book_list = g_list_remove (book_list, book); 00096 LEAVE (" "); 00097 } 00098 00099 gboolean 00100 qof_object_is_dirty (QofBook * book) 00101 { 00102 GList *l; 00103 00104 if (!book) 00105 return FALSE; 00106 for (l = object_modules; l; l = l->next) 00107 { 00108 QofObject *obj = l->data; 00109 if (obj->is_dirty) 00110 { 00111 QofCollection *col; 00112 col = qof_book_get_collection (book, obj->e_type); 00113 if (obj->is_dirty (col)) 00114 return TRUE; 00115 } 00116 } 00117 return FALSE; 00118 } 00119 00120 void 00121 qof_object_mark_clean (QofBook * book) 00122 { 00123 GList *l; 00124 00125 if (!book) 00126 return; 00127 for (l = object_modules; l; l = l->next) 00128 { 00129 QofObject *obj = l->data; 00130 if (obj->mark_clean) 00131 { 00132 QofCollection *col; 00133 col = qof_book_get_collection (book, obj->e_type); 00134 (obj->mark_clean) (col); 00135 } 00136 } 00137 } 00138 00139 void 00140 qof_object_foreach_type (QofForeachTypeCB cb, gpointer user_data) 00141 { 00142 GList *l; 00143 00144 if (!cb) 00145 return; 00146 00147 for (l = object_modules; l; l = l->next) 00148 { 00149 QofObject *obj = l->data; 00150 (cb) (obj, user_data); 00151 } 00152 } 00153 00154 gboolean 00155 qof_object_compliance (QofIdTypeConst type_name, gboolean warn) 00156 { 00157 const QofObject *obj; 00158 00159 obj = qof_object_lookup (type_name); 00160 if ((obj->create == NULL) || (obj->foreach == NULL)) 00161 { 00162 if (warn) 00163 { 00164 PINFO (" Object type %s is not fully QOF compliant", 00165 obj->e_type); 00166 } 00167 return FALSE; 00168 } 00169 return TRUE; 00170 } 00171 00172 00173 void 00174 qof_object_foreach (QofIdTypeConst type_name, QofBook * book, 00175 QofEntityForeachCB cb, gpointer user_data) 00176 { 00177 QofCollection *col; 00178 const QofObject *obj; 00179 00180 if (!book || !type_name) 00181 { 00182 return; 00183 } 00184 PINFO ("type=%s", type_name); 00185 00186 obj = qof_object_lookup (type_name); 00187 if (!obj) 00188 { 00189 PERR ("No object of type %s", type_name); 00190 return; 00191 } 00192 col = qof_book_get_collection (book, obj->e_type); 00193 if (!obj) 00194 { 00195 return; 00196 } 00197 if (obj->foreach) 00198 { 00199 obj->foreach (col, cb, user_data); 00200 } 00201 return; 00202 } 00203 00204 const gchar * 00205 qof_object_printable (QofIdTypeConst type_name, gpointer obj) 00206 { 00207 const QofObject *b_obj; 00208 00209 if (!type_name || !obj) 00210 return NULL; 00211 00212 b_obj = qof_object_lookup (type_name); 00213 if (!b_obj) 00214 return NULL; 00215 00216 if (b_obj->printable) 00217 return (b_obj->printable (obj)); 00218 00219 return NULL; 00220 } 00221 00222 const gchar * 00223 qof_object_get_type_label (QofIdTypeConst type_name) 00224 { 00225 const QofObject *obj; 00226 00227 if (!type_name) 00228 return NULL; 00229 00230 obj = qof_object_lookup (type_name); 00231 if (!obj) 00232 return NULL; 00233 00234 return (obj->type_label); 00235 } 00236 00237 static gboolean 00238 clear_table (gpointer key __attribute__ ((unused)), gpointer value, 00239 gpointer user_data __attribute__ ((unused))) 00240 { 00241 g_hash_table_destroy (value); 00242 return TRUE; 00243 } 00244 00245 /* INITIALIZATION and PRIVATE FUNCTIONS */ 00246 00247 void 00248 qof_object_initialize (void) 00249 { 00250 if (object_is_initialized) 00251 return; 00252 backend_data = g_hash_table_new (g_str_hash, g_str_equal); 00253 object_is_initialized = TRUE; 00254 } 00255 00256 void 00257 qof_object_shutdown (void) 00258 { 00259 g_return_if_fail (object_is_initialized == TRUE); 00260 00261 g_hash_table_foreach_remove (backend_data, clear_table, NULL); 00262 g_hash_table_destroy (backend_data); 00263 backend_data = NULL; 00264 00265 g_list_free (object_modules); 00266 object_modules = NULL; 00267 g_list_free (book_list); 00268 book_list = NULL; 00269 object_is_initialized = FALSE; 00270 } 00271 00272 /* Register new types of object objects. 00273 * Return TRUE if successful, 00274 * return FALSE if it fails, invalid arguments, or if the object 00275 * already exists 00276 */ 00277 gboolean 00278 qof_object_register (const QofObject * object) 00279 { 00280 g_return_val_if_fail (object_is_initialized, FALSE); 00281 00282 if (!object) 00283 return FALSE; 00284 g_return_val_if_fail (object->interface_version == QOF_OBJECT_VERSION, 00285 FALSE); 00286 00287 if (g_list_index (object_modules, (gpointer) object) == -1) 00288 object_modules = 00289 g_list_prepend (object_modules, (gpointer) object); 00290 else 00291 return FALSE; 00292 00293 /* Now initialize all the known books */ 00294 if (object->book_begin && book_list) 00295 { 00296 GList *node; 00297 for (node = book_list; node; node = node->next) 00298 object->book_begin (node->data); 00299 } 00300 00301 return TRUE; 00302 } 00303 00304 const QofObject * 00305 qof_object_lookup (QofIdTypeConst name) 00306 { 00307 GList *qiter; 00308 const QofObject *obj; 00309 00310 g_return_val_if_fail (object_is_initialized, NULL); 00311 00312 if (!name) 00313 return NULL; 00314 00315 for (qiter = object_modules; qiter; qiter = qiter->next) 00316 { 00317 obj = qiter->data; 00318 if (!safe_strcmp (obj->e_type, name)) 00319 return obj; 00320 } 00321 return NULL; 00322 } 00323 00324 gboolean 00325 qof_object_register_backend (QofIdTypeConst type_name, 00326 const gchar * backend_name, gpointer be_data) 00327 { 00328 GHashTable *ht; 00329 g_return_val_if_fail (object_is_initialized, FALSE); 00330 00331 if (!type_name || *type_name == '\0' || 00332 !backend_name || *backend_name == '\0' || !be_data) 00333 return FALSE; 00334 00335 ht = g_hash_table_lookup (backend_data, backend_name); 00336 00337 /* If it doesn't already exist, create a new table for this backend */ 00338 if (!ht) 00339 { 00340 ht = g_hash_table_new (g_str_hash, g_str_equal); 00341 g_hash_table_insert (backend_data, (gchar *) backend_name, ht); 00342 } 00343 00344 /* Now insert the data */ 00345 g_hash_table_insert (ht, (gchar *) type_name, be_data); 00346 00347 return TRUE; 00348 } 00349 00350 gpointer 00351 qof_object_lookup_backend (QofIdTypeConst type_name, 00352 const gchar * backend_name) 00353 { 00354 GHashTable *ht; 00355 00356 if (!type_name || *type_name == '\0' || 00357 !backend_name || *backend_name == '\0') 00358 return NULL; 00359 00360 ht = g_hash_table_lookup (backend_data, (gchar *) backend_name); 00361 if (!ht) 00362 return NULL; 00363 00364 return g_hash_table_lookup (ht, (gchar *) type_name); 00365 } 00366 00367 struct foreach_data 00368 { 00369 QofForeachBackendTypeCB cb; 00370 gpointer user_data; 00371 }; 00372 00373 static void 00374 foreach_backend (gpointer key, gpointer be_item, gpointer arg) 00375 { 00376 gchar *data_type = key; 00377 struct foreach_data *cb_data = arg; 00378 00379 g_return_if_fail (key && be_item && arg); 00380 00381 /* Call the callback for this data type */ 00382 (cb_data->cb) (data_type, be_item, cb_data->user_data); 00383 } 00384 00385 void 00386 qof_object_foreach_backend (const gchar * backend_name, 00387 QofForeachBackendTypeCB cb, gpointer user_data) 00388 { 00389 GHashTable *ht; 00390 struct foreach_data cb_data; 00391 00392 if (!backend_name || *backend_name == '\0' || !cb) 00393 return; 00394 00395 ht = g_hash_table_lookup (backend_data, (gchar *) backend_name); 00396 if (!ht) 00397 return; 00398 00399 cb_data.cb = cb; 00400 cb_data.user_data = user_data; 00401 00402 g_hash_table_foreach (ht, foreach_backend, &cb_data); 00403 } 00404 00405 /* ========================= END OF FILE =================== */