GnuCash 2.4.99
qofinstance.c
00001 /********************************************************************\
00002  * qofinstance.c -- handler for fields common to all objects        *
00003  *                                                                  *
00004  * This program is free software; you can redistribute it and/or    *
00005  * modify it under the terms of the GNU General Public License as   *
00006  * published by the Free Software Foundation; either version 2 of   *
00007  * the License, or (at your option) any later version.              *
00008  *                                                                  *
00009  * This program is distributed in the hope that it will be useful,  *
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of   *
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    *
00012  * GNU General Public License for more details.                     *
00013  *                                                                  *
00014  * You should have received a copy of the GNU General Public License*
00015  * along with this program; if not, contact:                        *
00016  *                                                                  *
00017  * Free Software Foundation           Voice:  +1-617-542-5942       *
00018  * 51 Franklin Street, Fifth Floor    Fax:    +1-617-542-2652       *
00019  * Boston, MA  02110-1301,  USA       gnu@gnu.org                   *
00020  *                                                                  *
00021 \********************************************************************/
00022 
00023 /*
00024  * Object instance holds many common fields that most
00025  * gnucash objects use.
00026  *
00027  * Copyright (C) 2003 Linas Vepstas <linas@linas.org>
00028  * Copyright (c) 2007 David Hampton <hampton@employees.org>
00029  */
00030 
00031 #include "config.h"
00032 #include <glib.h>
00033 #include "qof.h"
00034 #include "kvp-util-p.h"
00035 #include "qofbook-p.h"
00036 #include "qofid-p.h"
00037 #include "qofinstance-p.h"
00038 
00039 static QofLogModule log_module = QOF_MOD_ENGINE;
00040 
00041 /* ========================================================== */
00042 
00043 enum
00044 {
00045     LAST_SIGNAL
00046 };
00047 
00048 enum
00049 {
00050     PROP_0,
00051     PROP_TYPE,
00052     PROP_GUID,
00053     PROP_COLLECTION,
00054     PROP_BOOK,
00055     PROP_KVP_DATA,
00056     PROP_LAST_UPDATE,
00057     PROP_EDITLEVEL,
00058     PROP_DESTROYING,
00059     PROP_DIRTY,
00060     PROP_INFANT,
00061 
00062     PROP_VERSION,
00063     PROP_VERSION_CHECK,
00064     PROP_IDATA,
00065 };
00066 
00067 typedef struct QofInstancePrivate
00068 {
00069 //    QofIdType        e_type;    /**<  Entity type */
00070     GncGUID guid;                  
00071     QofCollection  *collection; 
00073     /* The entity_table in which this instance is stored */
00074     QofBook * book;
00075 
00076     /* kvp_data is a key-value pair database for storing arbirtary
00077      * information associated with this instance.
00078      * See src/engine/kvp_doc.txt for a list and description of the
00079      * important keys. */
00080 //    KvpFrame *kvp_data;
00081 
00082     /*  Timestamp used to track the last modification to this
00083      *  instance.  Typically used to compare two versions of the
00084      *  same object, to see which is newer.  When used with the
00085      *  SQL backend, this field is reserved for SQL use, to compare
00086      *  the version in local memory to the remote, server version.
00087      */
00088     Timespec last_update;
00089 
00090     /*  Keep track of nesting level of begin/end edit calls */
00091     int editlevel;
00092 
00093     /*  In process of being destroyed */
00094     gboolean do_free;
00095 
00096     /*  dirty/clean flag. If dirty, then this instance has been modified,
00097      *  but has not yet been written out to storage (file/database)
00098      */
00099     gboolean dirty;
00100 
00101     /* True iff this instance has never been committed. */
00102     gboolean infant;
00103 
00104     /* version number, used for tracking multiuser updates */
00105     gint32 version;
00106     guint32 version_check;  /* data aging timestamp */
00107 
00108     /* -------------------------------------------------------------- */
00109     /* Backend private expansion data */
00110     guint32  idata;   /* used by the sql backend for kvp management */
00111 }  QofInstancePrivate;
00112 
00113 #define GET_PRIVATE(o)  \
00114    (G_TYPE_INSTANCE_GET_PRIVATE ((o), QOF_TYPE_INSTANCE,  QofInstancePrivate))
00115 
00116 QOF_GOBJECT_GET_TYPE(QofInstance, qof_instance, G_TYPE_OBJECT, {});
00117 QOF_GOBJECT_FINALIZE(qof_instance);
00118 
00119 static void qof_instance_get_property (GObject         *object,
00120                                        guint            prop_id,
00121                                        GValue          *value,
00122                                        GParamSpec      *pspec);
00123 static void qof_instance_set_property (GObject         *object,
00124                                        guint            prop_id,
00125                                        const GValue    *value,
00126                                        GParamSpec      *pspec);
00127 static void qof_instance_dispose(GObject*);
00128 static void qof_instance_class_init(QofInstanceClass *klass)
00129 {
00130     GObjectClass *object_class = G_OBJECT_CLASS(klass);
00131     object_class->finalize = qof_instance_finalize;
00132     object_class->dispose = qof_instance_dispose;
00133     object_class->set_property = qof_instance_set_property;
00134     object_class->get_property = qof_instance_get_property;
00135 
00136     g_type_class_add_private(klass, sizeof(QofInstancePrivate));
00137 
00138     klass->get_display_name = NULL;
00139     klass->refers_to_object = NULL;
00140     klass->get_typed_referring_object_list = NULL;
00141 
00142     g_object_class_install_property
00143     (object_class,
00144      PROP_GUID,
00145      g_param_spec_boxed ("guid",
00146                          "Object GncGUID",
00147                          "The object Globally Unique ID.",
00148                          GNC_TYPE_GUID,
00149                          G_PARAM_READWRITE));
00150 
00151     g_object_class_install_property
00152     (object_class,
00153      PROP_COLLECTION,
00154      g_param_spec_pointer ("collection",
00155                            "Object Collection",
00156                            "A collection of like objects of which this "
00157                            "particular object is amember.  E.g.. A "
00158                            "collection of accounts, or a collection of "
00159                            "splits.",
00160                            G_PARAM_READWRITE));
00161 
00162     g_object_class_install_property
00163     (object_class,
00164      PROP_BOOK,
00165      g_param_spec_object ("book",
00166                           "Object Book",
00167                           "The book that contains this object.",
00168                           QOF_TYPE_BOOK,
00169                           G_PARAM_READWRITE));
00170 
00171     g_object_class_install_property
00172     (object_class,
00173      PROP_KVP_DATA,
00174      g_param_spec_pointer ("kvp-data",
00175                            "Object KVP Data",
00176                            "A pointer to the key-value data associated "
00177                            "with this object.",
00178                            G_PARAM_READWRITE));
00179 
00180     g_object_class_install_property
00181     (object_class,
00182      PROP_LAST_UPDATE,
00183      g_param_spec_pointer ("last-update",
00184                            "Object Last Update",
00185                            "A pointer to the last time this object was "
00186                            "updated.  This value is present for use by "
00187                            "backends and shouldnot be written by other "
00188                            "code.",
00189                            G_PARAM_READWRITE));
00190 
00191     g_object_class_install_property
00192     (object_class,
00193      PROP_EDITLEVEL,
00194      g_param_spec_int ("editlevel",
00195                        "Object Edit Level",
00196                        "The object edit level.",
00197                        0, G_MAXINT32, 0,
00198                        G_PARAM_READABLE));
00199 
00200     g_object_class_install_property
00201     (object_class,
00202      PROP_DESTROYING,
00203      g_param_spec_boolean ("destroying",
00204                            "Object Destroying",
00205                            "This flag is set to TRUE if the object is "
00206                            "about to be destroyed.",
00207                            FALSE,
00208                            G_PARAM_READWRITE));
00209 
00210     g_object_class_install_property
00211     (object_class,
00212      PROP_DIRTY,
00213      g_param_spec_boolean ("dirty",
00214                            "Object Dirty",
00215                            "This flag is set to TRUE if the object has "
00216                            "unsaved changes.",
00217                            FALSE,
00218                            G_PARAM_READWRITE));
00219 
00220     g_object_class_install_property
00221     (object_class,
00222      PROP_INFANT,
00223      g_param_spec_boolean ("infant",
00224                            "Object Infant",
00225                            "This flag is set to TRUE if the object has "
00226                            "never been added to a book.  This implies "
00227                            "that its destruction does not affect the "
00228                            "state of the book, and therefore the saved "
00229                            "state of the data file.",
00230                            FALSE,
00231                            G_PARAM_READABLE));
00232 
00233     g_object_class_install_property
00234     (object_class,
00235      PROP_VERSION,
00236      g_param_spec_int ("version",
00237                        "Version",
00238                        "The version number of the current instance state.",
00239                        0,
00240                        G_MAXINT32,
00241                        0,
00242                        G_PARAM_READWRITE));
00243 
00244     g_object_class_install_property
00245     (object_class,
00246      PROP_VERSION_CHECK,
00247      g_param_spec_uint ("version-check",
00248                         "Version Check",
00249                         "The version check number of the current instance state.",
00250                         0,
00251                         G_MAXUINT32,
00252                         0,
00253                         G_PARAM_READWRITE));
00254 
00255     g_object_class_install_property
00256     (object_class,
00257      PROP_EDITLEVEL,
00258      g_param_spec_uint ("idata",
00259                         "Object IData",
00260                         "Per instance backend private data.",
00261                         0, G_MAXUINT32, 0,
00262                         G_PARAM_READWRITE));
00263 }
00264 
00265 static void
00266 qof_instance_init (QofInstance *inst)
00267 {
00268     QofInstancePrivate *priv;
00269 
00270     priv = GET_PRIVATE(inst);
00271     priv->book = NULL;
00272     inst->kvp_data = kvp_frame_new();
00273     priv->last_update.tv_sec = 0;
00274     priv->last_update.tv_nsec = -1;
00275     priv->editlevel = 0;
00276     priv->do_free = FALSE;
00277     priv->dirty = FALSE;
00278     priv->infant = TRUE;
00279 }
00280 
00281 void
00282 qof_instance_init_data (QofInstance *inst, QofIdType type, QofBook *book)
00283 {
00284     QofInstancePrivate *priv;
00285     QofCollection *col;
00286     QofIdType col_type;
00287 
00288     g_return_if_fail(QOF_IS_INSTANCE(inst));
00289     priv = GET_PRIVATE(inst);
00290     g_return_if_fail(!priv->book);
00291 
00292     priv->book = book;
00293     col = qof_book_get_collection (book, type);
00294     g_return_if_fail(col != NULL);
00295 
00296     /* XXX We passed redundant info to this routine ... but I think that's
00297      * OK, it might eliminate programming errors. */
00298 
00299     col_type = qof_collection_get_type(col);
00300     if (safe_strcmp(col_type, type))
00301     {
00302         PERR ("attempt to insert \"%s\" into \"%s\"", type, col_type);
00303         return;
00304     }
00305     priv = GET_PRIVATE(inst);
00306     inst->e_type = CACHE_INSERT (type);
00307 
00308     do
00309     {
00310         guid_new(&priv->guid);
00311 
00312         if (NULL == qof_collection_lookup_entity (col, &priv->guid))
00313             break;
00314 
00315         PWARN("duplicate id created, trying again");
00316     }
00317     while (1);
00318 
00319     priv->collection = col;
00320 
00321     qof_collection_insert_entity (col, inst);
00322 }
00323 
00324 static void
00325 qof_instance_dispose (GObject *instp)
00326 {
00327     QofInstancePrivate *priv;
00328     QofInstance* inst = QOF_INSTANCE(instp);
00329 
00330     priv = GET_PRIVATE(instp);
00331     if (!priv->collection)
00332         return;
00333     qof_collection_remove_entity(inst);
00334 
00335     CACHE_REMOVE(inst->e_type);
00336     inst->e_type = NULL;
00337 
00338     G_OBJECT_CLASS(qof_instance_parent_class)->dispose(instp);
00339 }
00340 
00341 static void
00342 qof_instance_finalize_real (GObject *instp)
00343 {
00344     QofInstancePrivate *priv;
00345     QofInstance* inst = QOF_INSTANCE(instp);
00346 
00347     kvp_frame_delete (inst->kvp_data);
00348     inst->kvp_data = NULL;
00349 
00350     priv = GET_PRIVATE(inst);
00351     priv->editlevel = 0;
00352     priv->do_free = FALSE;
00353     priv->dirty = FALSE;
00354 }
00355 
00356 static void
00357 qof_instance_get_property (GObject         *object,
00358                            guint            prop_id,
00359                            GValue          *value,
00360                            GParamSpec      *pspec)
00361 {
00362     QofInstance *inst;
00363     QofInstancePrivate *priv;
00364 
00365     g_return_if_fail(QOF_IS_INSTANCE(object));
00366 
00367     inst = QOF_INSTANCE(object);
00368     priv = GET_PRIVATE(inst);
00369 
00370     switch (prop_id)
00371     {
00372     case PROP_GUID:
00373         g_value_set_boxed(value, &priv->guid);
00374         break;
00375     case PROP_COLLECTION:
00376         g_value_set_pointer(value, priv->collection);
00377         break;
00378     case PROP_BOOK:
00379         g_value_set_object(value, priv->book);
00380         break;
00381     case PROP_KVP_DATA:
00382         g_value_set_pointer(value, inst->kvp_data);
00383         break;
00384     case PROP_LAST_UPDATE:
00385         g_value_set_pointer(value, &priv->last_update);
00386         break;
00387     case PROP_EDITLEVEL:
00388         g_value_set_int(value, priv->editlevel);
00389         break;
00390     case PROP_DESTROYING:
00391         g_value_set_boolean(value, priv->do_free);
00392         break;
00393     case PROP_DIRTY:
00394         g_value_set_boolean(value, qof_instance_get_dirty(inst));
00395         break;
00396     case PROP_INFANT:
00397         g_value_set_boolean(value, priv->infant);
00398         break;
00399     case PROP_VERSION:
00400         g_value_set_int(value, priv->version);
00401         break;
00402     case PROP_VERSION_CHECK:
00403         g_value_set_uint(value, priv->version_check);
00404         break;
00405     case PROP_IDATA:
00406         g_value_set_uint(value, priv->idata);
00407         break;
00408     default:
00409         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
00410         break;
00411     }
00412 }
00413 
00414 static void
00415 qof_instance_set_property (GObject         *object,
00416                            guint            prop_id,
00417                            const GValue    *value,
00418                            GParamSpec      *pspec)
00419 {
00420     QofInstance *inst;
00421     QofInstancePrivate *priv;
00422     Timespec *ts;
00423 
00424     g_return_if_fail(QOF_IS_INSTANCE(object));
00425 
00426     inst = QOF_INSTANCE(object);
00427     priv = GET_PRIVATE(inst);
00428 
00429     switch (prop_id)
00430     {
00431     case PROP_GUID:
00432         qof_instance_set_guid(inst, g_value_get_boxed(value));
00433         break;
00434     case PROP_COLLECTION:
00435         qof_instance_set_collection(inst, g_value_get_pointer(value));
00436         break;
00437     case PROP_BOOK:
00438         qof_instance_set_book(inst, g_value_get_object(value));
00439         break;
00440     case PROP_KVP_DATA:
00441         qof_instance_set_slots(inst, g_value_get_pointer(value));
00442         break;
00443     case PROP_LAST_UPDATE:
00444         ts = g_value_get_pointer(value);
00445         qof_instance_set_last_update(inst, *ts);
00446         break;
00447     case PROP_DESTROYING:
00448         qof_instance_set_destroying(inst, g_value_get_boolean(value));
00449         break;
00450     case PROP_DIRTY:
00451         qof_instance_set_dirty(inst);
00452         break;
00453     case PROP_VERSION:
00454         qof_instance_set_version(inst, g_value_get_int(value));
00455         break;
00456     case PROP_VERSION_CHECK:
00457         qof_instance_set_version_check(inst, g_value_get_uint(value));
00458         break;
00459     case PROP_IDATA:
00460         qof_instance_set_idata(inst, g_value_get_uint(value));
00461         break;
00462     default:
00463         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
00464         break;
00465     }
00466 }
00467 
00468 const GncGUID *
00469 qof_instance_get_guid (gconstpointer inst)
00470 {
00471     QofInstancePrivate *priv;
00472 
00473     if (!inst) return NULL;
00474     g_return_val_if_fail(QOF_IS_INSTANCE(inst), guid_null());
00475     priv = GET_PRIVATE(inst);
00476     return &(priv->guid);
00477 }
00478 
00479 const GncGUID *
00480 qof_entity_get_guid (gconstpointer ent)
00481 {
00482     return ent ? qof_instance_get_guid(ent) : guid_null();
00483 }
00484 
00485 void
00486 qof_instance_set_guid (gpointer ptr, const GncGUID *guid)
00487 {
00488     QofInstancePrivate *priv;
00489     QofInstance *inst;
00490     QofCollection *col;
00491 
00492     g_return_if_fail(QOF_IS_INSTANCE(ptr));
00493 
00494     inst = QOF_INSTANCE(ptr);
00495     priv = GET_PRIVATE(inst);
00496     if (guid_equal (guid, &priv->guid))
00497         return;
00498 
00499     col = priv->collection;
00500     qof_collection_remove_entity(inst);
00501     priv->guid = *guid;
00502     qof_collection_insert_entity(col, inst);
00503 }
00504 
00505 void
00506 qof_instance_copy_guid (gpointer to, gconstpointer from)
00507 {
00508     g_return_if_fail(QOF_IS_INSTANCE(to));
00509     g_return_if_fail(QOF_IS_INSTANCE(from));
00510 
00511     GET_PRIVATE(to)->guid = GET_PRIVATE(from)->guid;
00512 }
00513 
00514 gint
00515 qof_instance_guid_compare(gconstpointer ptr1, gconstpointer ptr2)
00516 {
00517     const QofInstancePrivate *priv1, *priv2;
00518 
00519     g_return_val_if_fail(QOF_IS_INSTANCE(ptr1), -1);
00520     g_return_val_if_fail(QOF_IS_INSTANCE(ptr2),  1);
00521 
00522     priv1 = GET_PRIVATE(ptr1);
00523     priv2 = GET_PRIVATE(ptr2);
00524 
00525     return guid_compare(&priv1->guid, &priv2->guid);
00526 }
00527 
00528 QofCollection *
00529 qof_instance_get_collection (gconstpointer ptr)
00530 {
00531 
00532     g_return_val_if_fail(QOF_IS_INSTANCE(ptr), NULL);
00533     return GET_PRIVATE(ptr)->collection;
00534 }
00535 
00536 void
00537 qof_instance_set_collection (gconstpointer ptr, QofCollection *col)
00538 {
00539     g_return_if_fail(QOF_IS_INSTANCE(ptr));
00540     GET_PRIVATE(ptr)->collection = col;
00541 }
00542 
00543 QofBook *
00544 qof_instance_get_book (gconstpointer inst)
00545 {
00546     if (!inst) return NULL;
00547     g_return_val_if_fail(QOF_IS_INSTANCE(inst), NULL);
00548     return GET_PRIVATE(inst)->book;
00549 }
00550 
00551 void
00552 qof_instance_set_book (gconstpointer inst, QofBook *book)
00553 {
00554     g_return_if_fail(QOF_IS_INSTANCE(inst));
00555     GET_PRIVATE(inst)->book = book;
00556 }
00557 
00558 void
00559 qof_instance_copy_book (gpointer ptr1, gconstpointer ptr2)
00560 {
00561     g_return_if_fail(QOF_IS_INSTANCE(ptr1));
00562     g_return_if_fail(QOF_IS_INSTANCE(ptr2));
00563 
00564     GET_PRIVATE(ptr1)->book = GET_PRIVATE(ptr2)->book;
00565 }
00566 
00567 gboolean
00568 qof_instance_books_equal (gconstpointer ptr1, gconstpointer ptr2)
00569 {
00570     const QofInstancePrivate *priv1, *priv2;
00571 
00572     g_return_val_if_fail(QOF_IS_INSTANCE(ptr1), FALSE);
00573     g_return_val_if_fail(QOF_IS_INSTANCE(ptr2), FALSE);
00574 
00575     priv1 = GET_PRIVATE(ptr1);
00576     priv2 = GET_PRIVATE(ptr2);
00577 
00578     return (priv1->book == priv2->book);
00579 }
00580 
00581 KvpFrame*
00582 qof_instance_get_slots (const QofInstance *inst)
00583 {
00584     if (!inst) return NULL;
00585     return inst->kvp_data;
00586 }
00587 
00588 void
00589 qof_instance_set_slots (QofInstance *inst, KvpFrame *frm)
00590 {
00591     QofInstancePrivate *priv;
00592 
00593     if (!inst) return;
00594 
00595     priv = GET_PRIVATE(inst);
00596     if (inst->kvp_data && (inst->kvp_data != frm))
00597     {
00598         kvp_frame_delete(inst->kvp_data);
00599     }
00600 
00601     priv->dirty = TRUE;
00602     inst->kvp_data = frm;
00603 }
00604 
00605 void
00606 qof_instance_set_last_update (QofInstance *inst, Timespec ts)
00607 {
00608     if (!inst) return;
00609     GET_PRIVATE(inst)->last_update = ts;
00610 }
00611 
00612 gint
00613 qof_instance_get_editlevel (gconstpointer ptr)
00614 {
00615     g_return_val_if_fail(QOF_IS_INSTANCE(ptr), 0);
00616     return GET_PRIVATE(ptr)->editlevel;
00617 }
00618 
00619 void qof_instance_increase_editlevel (gpointer ptr)
00620 {
00621     g_return_if_fail(QOF_IS_INSTANCE(ptr));
00622     GET_PRIVATE(ptr)->editlevel++;
00623 }
00624 
00625 void qof_instance_decrease_editlevel (gpointer ptr)
00626 {
00627     g_return_if_fail(QOF_IS_INSTANCE(ptr));
00628     GET_PRIVATE(ptr)->editlevel--;
00629 }
00630 
00631 void qof_instance_reset_editlevel (gpointer ptr)
00632 {
00633     g_return_if_fail(QOF_IS_INSTANCE(ptr));
00634     GET_PRIVATE(ptr)->editlevel = 0;
00635 }
00636 
00637 int
00638 qof_instance_version_cmp (const QofInstance *left, const QofInstance *right)
00639 {
00640     QofInstancePrivate *lpriv, *rpriv;
00641 
00642     if (!left && !right) return 0;
00643     if (!left) return -1;
00644     if (!right) return +1;
00645 
00646     lpriv = GET_PRIVATE(left);
00647     rpriv = GET_PRIVATE(right);
00648     if (lpriv->last_update.tv_sec  < rpriv->last_update.tv_sec) return -1;
00649     if (lpriv->last_update.tv_sec  > rpriv->last_update.tv_sec) return +1;
00650     if (lpriv->last_update.tv_nsec < rpriv->last_update.tv_nsec) return -1;
00651     if (lpriv->last_update.tv_nsec > rpriv->last_update.tv_nsec) return +1;
00652     return 0;
00653 }
00654 
00655 gboolean
00656 qof_instance_get_destroying (gconstpointer ptr)
00657 {
00658     g_return_val_if_fail(QOF_IS_INSTANCE(ptr), FALSE);
00659     return GET_PRIVATE(ptr)->do_free;
00660 }
00661 
00662 void
00663 qof_instance_set_destroying (gpointer ptr, gboolean value)
00664 {
00665     g_return_if_fail(QOF_IS_INSTANCE(ptr));
00666     GET_PRIVATE(ptr)->do_free = value;
00667 }
00668 
00669 gboolean
00670 qof_instance_get_dirty_flag (gconstpointer ptr)
00671 {
00672     g_return_val_if_fail(QOF_IS_INSTANCE(ptr), FALSE);
00673     return GET_PRIVATE(ptr)->dirty;
00674 }
00675 
00676 void
00677 qof_instance_set_dirty_flag (gconstpointer inst, gboolean flag)
00678 {
00679     g_return_if_fail(QOF_IS_INSTANCE(inst));
00680     GET_PRIVATE(inst)->dirty = flag;
00681 }
00682 
00683 void
00684 qof_instance_mark_clean (QofInstance *inst)
00685 {
00686     if (!inst) return;
00687     GET_PRIVATE(inst)->dirty = FALSE;
00688 }
00689 
00690 void
00691 qof_instance_print_dirty (const QofInstance *inst, gpointer dummy)
00692 {
00693     QofInstancePrivate *priv;
00694 
00695     priv = GET_PRIVATE(inst);
00696     if (priv->dirty)
00697     {
00698         printf("%s instance %s is dirty.\n", inst->e_type,
00699                guid_to_string(&priv->guid));
00700     }
00701 }
00702 
00703 gboolean
00704 qof_instance_get_dirty (QofInstance *inst)
00705 {
00706     QofInstancePrivate *priv;
00707     QofCollection *coll;
00708 
00709     if (!inst)
00710     {
00711         return FALSE;
00712     }
00713 
00714     priv = GET_PRIVATE(inst);
00715     if (qof_get_alt_dirty_mode())
00716         return priv->dirty;
00717     coll = priv->collection;
00718     if (qof_collection_is_dirty(coll))
00719     {
00720         return priv->dirty;
00721     }
00722     priv->dirty = FALSE;
00723     return FALSE;
00724 }
00725 
00726 void
00727 qof_instance_set_dirty(QofInstance* inst)
00728 {
00729     QofInstancePrivate *priv;
00730     QofCollection *coll;
00731 
00732     priv = GET_PRIVATE(inst);
00733     priv->dirty = TRUE;
00734     if (!qof_get_alt_dirty_mode())
00735     {
00736         coll = priv->collection;
00737         qof_collection_mark_dirty(coll);
00738     }
00739 }
00740 
00741 gboolean
00742 qof_instance_get_infant(const QofInstance *inst)
00743 {
00744     g_return_val_if_fail(QOF_IS_INSTANCE(inst), FALSE);
00745     return GET_PRIVATE(inst)->infant;
00746 }
00747 
00748 gint32
00749 qof_instance_get_version (gconstpointer inst)
00750 {
00751     g_return_val_if_fail(QOF_IS_INSTANCE(inst), 0);
00752     return GET_PRIVATE(inst)->version;
00753 }
00754 
00755 void
00756 qof_instance_set_version (gpointer inst, gint32 vers)
00757 {
00758     g_return_if_fail(QOF_IS_INSTANCE(inst));
00759     GET_PRIVATE(inst)->version = vers;
00760 }
00761 
00762 void
00763 qof_instance_copy_version (gpointer to, gconstpointer from)
00764 {
00765     g_return_if_fail(QOF_IS_INSTANCE(to));
00766     g_return_if_fail(QOF_IS_INSTANCE(from));
00767     GET_PRIVATE(to)->version = GET_PRIVATE(from)->version;
00768 }
00769 
00770 guint32
00771 qof_instance_get_version_check (gconstpointer inst)
00772 {
00773     g_return_val_if_fail(QOF_IS_INSTANCE(inst), 0);
00774     return GET_PRIVATE(inst)->version_check;
00775 }
00776 
00777 void
00778 qof_instance_set_version_check (gpointer inst, guint32 value)
00779 {
00780     g_return_if_fail(QOF_IS_INSTANCE(inst));
00781     GET_PRIVATE(inst)->version_check = value;
00782 }
00783 
00784 void
00785 qof_instance_copy_version_check (gpointer to, gconstpointer from)
00786 {
00787     g_return_if_fail(QOF_IS_INSTANCE(to));
00788     g_return_if_fail(QOF_IS_INSTANCE(from));
00789     GET_PRIVATE(to)->version_check = GET_PRIVATE(from)->version_check;
00790 }
00791 
00792 guint32 qof_instance_get_idata (gconstpointer inst)
00793 {
00794     if (!inst)
00795     {
00796         return 0;
00797     }
00798     g_return_val_if_fail(QOF_IS_INSTANCE(inst), 0);
00799     return GET_PRIVATE(inst)->idata;
00800 }
00801 
00802 void qof_instance_set_idata(gpointer inst, guint32 idata)
00803 {
00804     if (!inst)
00805     {
00806         return;
00807     }
00808     if (idata < 0)
00809     {
00810         return;
00811     }
00812     g_return_if_fail(QOF_IS_INSTANCE(inst));
00813     GET_PRIVATE(inst)->idata = idata;
00814 }
00815 
00816 /* ========================================================== */
00817 
00818 /* Returns a displayable name to represent this object */
00819 gchar* qof_instance_get_display_name(const QofInstance* inst)
00820 {
00821     g_return_val_if_fail( inst != NULL, NULL );
00822 
00823     if ( QOF_INSTANCE_GET_CLASS(inst)->get_display_name != NULL )
00824     {
00825         return QOF_INSTANCE_GET_CLASS(inst)->get_display_name(inst);
00826     }
00827     else
00828     {
00829         /* Not implemented - return default string */
00830         return g_strdup_printf("Object %s %p",
00831                                qof_collection_get_type(qof_instance_get_collection(inst)),
00832                                inst);
00833     }
00834 }
00835 
00836 typedef struct
00837 {
00838     const QofInstance* inst;
00839     GList* list;
00840 } GetReferringObjectHelperData;
00841 
00842 static void
00843 get_referring_object_instance_helper(QofInstance* inst, gpointer user_data)
00844 {
00845     QofInstance** pInst = (QofInstance**)user_data;
00846 
00847     if (*pInst == NULL)
00848     {
00849         *pInst = inst;
00850     }
00851 }
00852 
00853 static void
00854 get_referring_object_helper(QofCollection* coll, gpointer user_data)
00855 {
00856     QofInstance* first_instance = NULL;
00857     GetReferringObjectHelperData* data = (GetReferringObjectHelperData*)user_data;
00858 
00859     qof_collection_foreach(coll, get_referring_object_instance_helper, &first_instance);
00860 
00861     if (first_instance != NULL)
00862     {
00863         GList* new_list = qof_instance_get_typed_referring_object_list(first_instance, data->inst);
00864         data->list = g_list_concat(data->list, new_list);
00865     }
00866 }
00867 
00868 /* Returns a list of objects referring to this object */
00869 GList* qof_instance_get_referring_object_list(const QofInstance* inst)
00870 {
00871     GetReferringObjectHelperData data;
00872 
00873     g_return_val_if_fail( inst != NULL, NULL );
00874 
00875     /* scan all collections */
00876     data.inst = inst;
00877     data.list = NULL;
00878 
00879     qof_book_foreach_collection(qof_instance_get_book(inst),
00880                                 get_referring_object_helper,
00881                                 &data);
00882     return data.list;
00883 }
00884 
00885 static void
00886 get_typed_referring_object_instance_helper(QofInstance* inst, gpointer user_data)
00887 {
00888     GetReferringObjectHelperData* data = (GetReferringObjectHelperData*)user_data;
00889 
00890     if (qof_instance_refers_to_object(inst, data->inst))
00891     {
00892         data->list = g_list_prepend(data->list, inst);
00893     }
00894 }
00895 
00896 GList*
00897 qof_instance_get_referring_object_list_from_collection(const QofCollection* coll, const QofInstance* ref)
00898 {
00899     GetReferringObjectHelperData data;
00900 
00901     g_return_val_if_fail( coll != NULL, NULL );
00902     g_return_val_if_fail( ref != NULL, NULL );
00903 
00904     data.inst = ref;
00905     data.list = NULL;
00906 
00907     qof_collection_foreach(coll, get_typed_referring_object_instance_helper, &data);
00908     return data.list;
00909 }
00910 
00911 GList*
00912 qof_instance_get_typed_referring_object_list(const QofInstance* inst, const QofInstance* ref)
00913 {
00914     g_return_val_if_fail( inst != NULL, NULL );
00915     g_return_val_if_fail( ref != NULL, NULL );
00916 
00917     if ( QOF_INSTANCE_GET_CLASS(inst)->get_typed_referring_object_list != NULL )
00918     {
00919         return QOF_INSTANCE_GET_CLASS(inst)->get_typed_referring_object_list(inst, ref);
00920     }
00921     else
00922     {
00923         /* Not implemented - by default, loop through all objects of this object's type and check
00924            them individually. */
00925         QofCollection* coll;
00926 
00927         coll = qof_instance_get_collection(inst);
00928         return qof_instance_get_referring_object_list_from_collection(coll, ref);
00929     }
00930 }
00931 
00932 /* Check if this object refers to a specific object */
00933 gboolean qof_instance_refers_to_object(const QofInstance* inst, const QofInstance* ref)
00934 {
00935     g_return_val_if_fail( inst != NULL, FALSE );
00936     g_return_val_if_fail( ref != NULL, FALSE );
00937 
00938     if ( QOF_INSTANCE_GET_CLASS(inst)->refers_to_object != NULL )
00939     {
00940         return QOF_INSTANCE_GET_CLASS(inst)->refers_to_object(inst, ref);
00941     }
00942     else
00943     {
00944         /* Not implemented - default = NO */
00945         return FALSE;
00946     }
00947 }
00948 
00949 /* =================================================================== */
00950 /* Entity edit and commit utilities */
00951 /* =================================================================== */
00952 
00953 gboolean
00954 qof_begin_edit (QofInstance *inst)
00955 {
00956     QofInstancePrivate *priv;
00957     QofBackend * be;
00958 
00959     if (!inst) return FALSE;
00960 
00961     priv = GET_PRIVATE(inst);
00962     priv->editlevel++;
00963     if (1 < priv->editlevel) return FALSE;
00964     if (0 >= priv->editlevel)
00965         priv->editlevel = 1;
00966 
00967     be = qof_book_get_backend(priv->book);
00968     if (be && qof_backend_begin_exists(be))
00969         qof_backend_run_begin(be, inst);
00970     else
00971         priv->dirty = TRUE;
00972 
00973     return TRUE;
00974 }
00975 
00976 gboolean qof_commit_edit (QofInstance *inst)
00977 {
00978     QofInstancePrivate *priv;
00979 
00980     if (!inst) return FALSE;
00981 
00982     priv = GET_PRIVATE(inst);
00983     priv->editlevel--;
00984     if (0 < priv->editlevel) return FALSE;
00985 
00986 #if 0
00987     if ((0 == priv->editlevel) && priv->dirty)
00988     {
00989         QofBackend * be = qof_book_get_backend(priv->book);
00990         if (be && qof_backend_commit_exists(be))
00991         {
00992             qof_backend_run_commit(be, inst);
00993         }
00994     }
00995 #endif
00996     if (0 > priv->editlevel)
00997     {
00998         PERR ("unbalanced call - resetting (was %d)", priv->editlevel);
00999         priv->editlevel = 0;
01000     }
01001     return TRUE;
01002 }
01003 
01004 gboolean
01005 qof_commit_edit_part2(QofInstance *inst,
01006                       void (*on_error)(QofInstance *, QofBackendError),
01007                       void (*on_done)(QofInstance *),
01008                       void (*on_free)(QofInstance *))
01009 {
01010     QofInstancePrivate *priv;
01011     QofBackend * be;
01012     gboolean dirty;
01013 
01014     priv = GET_PRIVATE(inst);
01015     dirty = priv->dirty;
01016 
01017     /* See if there's a backend.  If there is, invoke it. */
01018     be = qof_book_get_backend(priv->book);
01019     if (be && qof_backend_commit_exists(be))
01020     {
01021         QofBackendError errcode;
01022 
01023         /* clear errors */
01024         do
01025         {
01026             errcode = qof_backend_get_error(be);
01027         }
01028         while (ERR_BACKEND_NO_ERR != errcode);
01029 
01030         qof_backend_run_commit(be, inst);
01031         errcode = qof_backend_get_error(be);
01032         if (ERR_BACKEND_NO_ERR != errcode)
01033         {
01034             /* XXX Should perform a rollback here */
01035             priv->do_free = FALSE;
01036 
01037             /* Push error back onto the stack */
01038             qof_backend_set_error (be, errcode);
01039             if (on_error)
01040                 on_error(inst, errcode);
01041             return FALSE;
01042         }
01043         /* XXX the backend commit code should clear dirty!! */
01044         priv->dirty = FALSE;
01045     }
01046 //    if (dirty && qof_get_alt_dirty_mode() &&
01047 //        !(priv->infant && priv->do_free)) {
01048 //      qof_collection_mark_dirty(priv->collection);
01049 //      qof_book_mark_dirty(priv->book);
01050 //    }
01051     priv->infant = FALSE;
01052 
01053     if (priv->do_free)
01054     {
01055         if (on_free)
01056             on_free(inst);
01057         return TRUE;
01058     }
01059 
01060     if (on_done)
01061         on_done(inst);
01062     return TRUE;
01063 }
01064 
01065 /* ========================== END OF FILE ======================= */
01066 
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines