diff --git a/src/engine/qofbook-p.h b/src/engine/qofbook-p.h new file mode 100644 index 0000000000..1f1d9e43fb --- /dev/null +++ b/src/engine/qofbook-p.h @@ -0,0 +1,104 @@ +/********************************************************************\ + * qof-book-p.h -- private functions for QOF books. * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * + * Boston, MA 02111-1307, USA gnu@gnu.org * + * * +\********************************************************************/ + +/* + * HISTORY: + * Created 2001 by Rob Browning + * Copyright (c) 2001 Rob Browning + * Copyright (c) 2001,2003 Linas Vepstas + */ + +#ifndef QOF_BOOK_P_H +#define QOF_BOOK_P_H + +#include "Backend.h" +#include "GNCIdP.h" +#include "kvp_frame.h" +#include "qofbook.h" + +struct _QofBook +{ + /* Unique guid for this book. */ + GUID guid; + + /* The kvp_frame provides a place for top-level data associated + * with this book. */ + kvp_frame *kvp_data; + + /* The entity table associates the GUIDs of all the objects + * belonging to this book, with their pointers to the respective + * objects. This allows a lookup of objects based on thier guid. + */ + GNCEntityTable *entity_table; + + /* In order to store arbitrary data, for extensibility, add a table + * that will be used to hold arbitrary pointers. + */ + GHashTable *data_tables; + + /* state flag: 'y' means 'open for editing', + * 'n' means 'book is closed' + */ + char book_open; + + /* dirty/clean flag. If dirty, then this book has been modified, + * but has not yet been written out to storage (file/database) + */ + gboolean dirty; + + /* version number, used for tracking multiuser updates */ + gint32 version; + + /* To be technically correct, backends belong to sessions and + * not books. So the pointer below "really shouldn't be here", + * except that it provides a nice convenience, avoiding a lookup + * from the session. Better solutions welcome ... */ + Backend *backend; + + /* -------------------------------------------------------------- */ + /* Backend private expansion data */ + guint32 idata; /* used by the sql backend for kvp management */ +}; + +/* + * These qof_book_set_*() routines are used by backends to + * initialize the pointers in the book structure to + * something that contains actual data. These routines + * should not be used otherwise. (Its somewhat questionable + * if the backends should even be doing this much, but for + * backwards compatibility, we leave these here.) + */ +void qof_book_set_guid(QofBook *book, GUID guid); +void qof_book_set_schedxactions( QofBook *book, GList *newList ); + +void qof_book_set_backend (QofBook *book, Backend *be); + +/* The qof_book_mark_saved() routine marks the book as having been + * saved (to a file, to a database). Used by backends to mark the + * notsaved flag as FALSE just after loading. Do not use otherwise! + */ +void qof_book_mark_saved(QofBook *book); + +/* Register books with the engine */ +gboolean qof_book_register (void); + +#endif /* QOF_BOOK_P_H */ diff --git a/src/engine/qofbook.c b/src/engine/qofbook.c new file mode 100644 index 0000000000..ffb9580aab --- /dev/null +++ b/src/engine/qofbook.c @@ -0,0 +1,306 @@ +/********************************************************************\ + * qofbook.c -- dataset access (set of accounting books) * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * + * Boston, MA 02111-1307, USA gnu@gnu.org * +\********************************************************************/ + +/* + * FILE: + * qofbook.c + * + * FUNCTION: + * Encapsulate all the information about a gnucash dataset. + * See src/doc/books.txt for design overview. + * + * HISTORY: + * Created by Linas Vepstas December 1998 + * Copyright (c) 1998-2001,2003 Linas Vepstas + * Copyright (c) 2000 Dave Peticolas + */ + +#include "config.h" + +#include +#include + +#include + +#include "Backend.h" +#include "BackendP.h" +#include "QueryObject.h" +#include "gnc-event.h" +#include "gnc-event-p.h" +#include "gnc-trace.h" +#include "gncObjectP.h" +#include "qofbook.h" +#include "qofbook-p.h" + +static short module = MOD_ENGINE; + +/* ====================================================================== */ +/* constructor / destructor */ + +static void +qof_book_init (QofBook *book) +{ + if (!book) return; + + book->entity_table = xaccEntityTableNew (); + + xaccGUIDNew(&book->guid, book); + xaccStoreEntity(book->entity_table, book, &book->guid, GNC_ID_BOOK); + + book->kvp_data = kvp_frame_new (); + + book->data_tables = g_hash_table_new (g_str_hash, g_str_equal); + + book->book_open = 'y'; + book->version = 0; + book->idata = 0; +} + +QofBook * +qof_book_new (void) +{ + QofBook *book; + + ENTER (" "); + book = g_new0(QofBook, 1); + qof_book_init(book); + gncObjectBookBegin (book); + +#if 0 + gnc_engine_generate_event (&book->guid, GNC_EVENT_CREATE); +#endif + LEAVE ("book=%p", book); + return book; +} + +void +qof_book_destroy (QofBook *book) +{ + if (!book) return; + + ENTER ("book=%p", book); + gnc_engine_force_event (&book->guid, GNC_EVENT_DESTROY); + + gncObjectBookEnd (book); + + xaccRemoveEntity (book->entity_table, &book->guid); + xaccEntityTableDestroy (book->entity_table); + book->entity_table = NULL; + + /* FIXME: Make sure the data_table is empty */ + g_hash_table_destroy (book->data_tables); + + g_free (book); + LEAVE ("book=%p", book); +} + +/* ====================================================================== */ +/* XXX this should probably be calling is_equal callbacks on gncObject */ + +gboolean +qof_book_equal (QofBook *book_1, QofBook *book_2) +{ + if (book_1 == book_2) return TRUE; + if (!book_1 || !book_2) return FALSE; + return TRUE; +} + +/* ====================================================================== */ + +gboolean +qof_book_not_saved(QofBook *book) +{ + if (!book) return FALSE; + + return(book->dirty || gncObjectIsDirty (book)); +} + +void +qof_book_mark_saved(QofBook *book) +{ + if (!book) return; + + book->dirty = FALSE; + gncObjectMarkClean (book); +} + +/* ====================================================================== */ +/* getters */ + +const GUID * +qof_book_get_guid (QofBook *book) +{ + if (!book) return NULL; + return &book->guid; +} + +kvp_frame * +qof_book_get_slots (QofBook *book) +{ + if (!book) return NULL; + return book->kvp_data; +} + +GNCEntityTable * +qof_book_get_entity_table (QofBook *book) +{ + if (!book) return NULL; + return book->entity_table; +} + +Backend * +xaccQofBookGetBackend (QofBook *book) +{ + if (!book) return NULL; + return book->backend; +} + +/* ====================================================================== */ +/* setters */ + +void +qof_book_set_guid (QofBook *book, GUID uid) +{ + if (!book) return; + + if (guid_equal (&book->guid, &uid)) return; + + xaccRemoveEntity(book->entity_table, &book->guid); + book->guid = uid; + xaccStoreEntity(book->entity_table, book, &book->guid, GNC_ID_BOOK); +} + +void +qof_book_set_backend (QofBook *book, Backend *be) +{ + if (!book) return; + ENTER ("book=%p be=%p", book, be); + book->backend = be; +} + +gpointer qof_book_get_backend (QofBook *book) +{ + if (!book) return NULL; + return (gpointer)book->backend; +} + + +void qof_book_kvp_changed (QofBook *book) +{ + if (!book) return; + book->dirty = TRUE; +} + +/* ====================================================================== */ + +/* Store arbitrary pointers in the QofBook for data storage extensibility */ +/* XXX if data is NULL, we ashould remove the key from the hash table! + * + * XXX We need some design comments: an equivalent storage mechanism + * would have been to give each item a GUID, store the GUID in a kvp frame, + * and then do a GUID lookup to get the pointer to the actual object. + * Of course, doing a kvp lookup followed by a GUID lookup would be + * a good bit slower, but may be that's OK? In most cases, book data + * is accessed only infrequently? --linas + */ +void +qof_book_set_data (QofBook *book, const char *key, gpointer data) +{ + if (!book || !key) return; + g_hash_table_insert (book->data_tables, (gpointer)key, data); +} + +gpointer +qof_book_get_data (QofBook *book, const char *key) +{ + if (!book || !key) return NULL; + return g_hash_table_lookup (book->data_tables, (gpointer)key); +} + +/* ====================================================================== */ + +gint64 +qof_book_get_counter (QofBook *book, const char *counter_name) +{ + Backend *be; + kvp_frame *kvp; + kvp_value *value; + gint64 counter; + + if (!book) { + PWARN ("No book!!!"); + return -1; + } + + if (!counter_name || *counter_name == '\0') { + PWARN ("Invalid counter name."); + return -1; + } + + /* If we've got a backend with a counter method, call it */ + be = book->backend; + if (be && be->counter) + return ((be->counter)(be, counter_name)); + + /* If not, then use the KVP in the book */ + kvp = qof_book_get_slots (book); + + if (!kvp) { + PWARN ("Book has no KVP_Frame"); + return -1; + } + + value = kvp_frame_get_slot_path (kvp, "counters", counter_name, NULL); + if (value) { + /* found it */ + counter = kvp_value_get_gint64 (value); + } else { + /* New counter */ + counter = 0; + } + + /* Counter is now valid; increment it */ + counter++; + + /* Save off the new counter */ + value = kvp_value_new_gint64 (counter); + kvp_frame_set_slot_path (kvp, value, "counters", counter_name, NULL); + kvp_value_delete (value); + + /* and return the value */ + return counter; +} + +/* gncObject function implementation and registration */ +gboolean qof_book_register (void) +{ + static QueryObjectDef params[] = { + { QOF_BOOK_KVP, QUERYCORE_KVP, (QueryAccess)qof_book_get_slots }, + { QUERY_PARAM_GUID, QUERYCORE_GUID, (QueryAccess)qof_book_get_guid }, + { NULL }, + }; + + gncQueryObjectRegister (GNC_ID_BOOK, NULL, params); + + return TRUE; +} + +/* ========================== END OF FILE =============================== */ diff --git a/src/engine/qofbook.h b/src/engine/qofbook.h new file mode 100644 index 0000000000..1b30020b76 --- /dev/null +++ b/src/engine/qofbook.h @@ -0,0 +1,112 @@ +/********************************************************************\ + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License as * + * published by the Free Software Foundation; either version 2 of * + * the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License* + * along with this program; if not, contact: * + * * + * Free Software Foundation Voice: +1-617-542-5942 * + * 59 Temple Place - Suite 330 Fax: +1-617-542-2652 * + * Boston, MA 02111-1307, USA gnu@gnu.org * + * * +\********************************************************************/ +/** @addtogroup Engine + @{ */ +/** @file qofbook.h + * @brief dataset access (an "accounting book") + * Encapsulate all the information about a dataset. + * See src/docs/books.txt for implementation overview. + * + * HISTORY: + * Created by Linas Vepstas December 1998 + * @author Copyright (c) 1998, 1999, 2001, 2003 Linas Vepstas + * @author Copyright (c) 2000 Dave Peticolas + */ + +#ifndef QOF_BOOK_H +#define QOF_BOOK_H + +#include + +#include "GNCId.h" +#include "kvp_frame.h" + +/** @brief Encapsulates all the information about a dataset + * manipulated by GnuCash. This is the top-most structure + * used for anchoring data. + */ +typedef struct _QofBook QofBook; + +/** GList of QofBook */ +typedef GList QofBookList; + +/** Allocate, initialise and return a new QofBook. Books contain references + * to all of the top-level object containers. */ +QofBook * qof_book_new (void); + +/** End any editing sessions associated with book, and free all memory + associated with it. */ +void qof_book_destroy (QofBook *book); + +/** \return The Entity table for the book. */ +GNCEntityTable * qof_book_get_entity_table (QofBook *book); + +/** \return The GUID for the book. */ +const GUID * qof_book_get_guid (QofBook *book); + +/** \return The kvp data for the book */ +kvp_frame * qof_book_get_slots (QofBook *book); + +/** The qof_book_set_data() allows + * arbitrary pointers to structs to be stored in QofBook. + * This is the "prefered" method for extending QofBook to hold + * new data types. + */ +void qof_book_set_data (QofBook *book, const char *key, gpointer data); + +/** Retreives arbitrary pointers to structs stored by qof_book_set_data. */ +gpointer qof_book_get_data (QofBook *book, const char *key); + +/** DOCUMENT ME! */ +gpointer qof_book_get_backend (QofBook *book); + +/** qof_book_not_saved() will return TRUE if any + * data in the book hasn't been saved to long-term storage. + * (Actually, that's not quite true. The book doesn't know + * anything about saving. Its just that whenever data is modified, + * the 'dirty' flag is set. This routine returns the value of the + * 'dirty' flag. Its up to the backend to periodically reset this + * flag, when it acutally does save the data.) + */ +gboolean qof_book_not_saved (QofBook *book); + +/** Call this function when you change the book kvp, to make sure the book + * is marked 'dirty'. */ +void qof_book_kvp_changed (QofBook *book); + +/** The qof_book_equal() method returns TRUE if books are equal. + * XXX this routine is broken, and does not currently compare data. + */ +gboolean qof_book_equal (QofBook *book_1, QofBook *book_2); + +/** This will 'get and increment' the named counter for this book. + * The return value is -1 on error or the incremented counter. + */ +gint64 qof_book_get_counter (QofBook *book, const char *counter_name); + +/** Book parameter names */ +/**@{*/ + +#define QOF_BOOK_KVP "qof-kvp" + +/**@}*/ + +#endif /* QOF_BOOK_H */ +/** @} */