GnuCash  5.6-150-g038405b370+
qofid.cpp
1 /********************************************************************\
2  * qofid.c -- QOF entity identifier implementation *
3  * Copyright (C) 2000 Dave Peticolas <dave@krondo.com> *
4  * Copyright (C) 2003 Linas Vepstas <linas@linas.org> *
5  * *
6  * This program is free software; you can redistribute it and/or *
7  * modify it under the terms of the GNU General Public License as *
8  * published by the Free Software Foundation; either version 2 of *
9  * the License, or (at your option) any later version. *
10  * *
11  * This program is distributed in the hope that it will be useful, *
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14  * GNU General Public License for more details. *
15  * *
16  * You should have received a copy of the GNU General Public License*
17  * along with this program; if not, contact: *
18  * *
19  * Free Software Foundation Voice: +1-617-542-5942 *
20  * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652 *
21  * Boston, MA 02110-1301, USA gnu@gnu.org *
22  * *
23 \********************************************************************/
24 
25 #include <glib.h>
26 
27 #include <config.h>
28 #include <string.h>
29 
30 #include "qof.h"
31 #include "qofid-p.h"
32 #include "qofinstance-p.h"
33 
34 static QofLogModule log_module = QOF_MOD_ENGINE;
35 
37 {
38  QofIdType e_type;
39  gboolean is_dirty;
40 
41  GHashTable * hash_of_entities;
42  gpointer data; /* place where object class can hang arbitrary data */
43 };
44 
45 /* =============================================================== */
46 
47 QofCollection *
49 {
50  QofCollection *col;
51  col = g_new0(QofCollection, 1);
52  col->e_type = static_cast<QofIdType>(CACHE_INSERT (type));
53  col->hash_of_entities = guid_hash_table_new();
54  col->data = NULL;
55  return col;
56 }
57 
58 void
59 qof_collection_destroy (QofCollection *col)
60 {
61  CACHE_REMOVE (col->e_type);
62  g_hash_table_destroy(col->hash_of_entities);
63  col->e_type = NULL;
64  col->hash_of_entities = NULL;
65  col->data = NULL;
66  g_free (col);
67 }
68 
69 /* =============================================================== */
70 /* getters */
71 
73 qof_collection_get_type (const QofCollection *col)
74 {
75  return col->e_type;
76 }
77 
78 /* =============================================================== */
79 
80 void
81 qof_collection_remove_entity (QofInstance *ent)
82 {
83  QofCollection *col;
84  const GncGUID *guid;
85 
86  if (!ent) return;
87  col = qof_instance_get_collection(ent);
88  if (!col) return;
89  guid = qof_instance_get_guid(ent);
90  g_hash_table_remove (col->hash_of_entities, guid);
91  qof_instance_set_collection(ent, NULL);
92 }
93 
94 void
95 qof_collection_insert_entity (QofCollection *col, QofInstance *ent)
96 {
97  const GncGUID *guid;
98 
99  if (!col || !ent) return;
100  guid = qof_instance_get_guid(ent);
101  if (guid_equal(guid, guid_null())) return;
102  g_return_if_fail (col->e_type == ent->e_type);
103  qof_collection_remove_entity (ent);
104  g_hash_table_insert (col->hash_of_entities, (gpointer)guid, ent);
105  qof_instance_set_collection(ent, col);
106 }
107 
108 gboolean
109 qof_collection_add_entity (QofCollection *coll, QofInstance *ent)
110 {
111  QofInstance *e;
112  const GncGUID *guid;
113 
114  e = NULL;
115  if (!coll || !ent)
116  {
117  return FALSE;
118  }
119  guid = qof_instance_get_guid(ent);
120  if (guid_equal(guid, guid_null()))
121  {
122  return FALSE;
123  }
124  g_return_val_if_fail (coll->e_type == ent->e_type, FALSE);
125  e = qof_collection_lookup_entity(coll, guid);
126  if ( e != NULL )
127  {
128  return FALSE;
129  }
130  g_hash_table_insert (coll->hash_of_entities, (gpointer)guid, ent);
131  return TRUE;
132 }
133 
134 
135 static void
136 collection_compare_cb (QofInstance *ent, gpointer user_data)
137 {
138  QofCollection *target;
139  QofInstance *e;
140  const GncGUID *guid;
141  gint value;
142 
143  e = NULL;
144  target = (QofCollection*)user_data;
145  if (!target || !ent)
146  {
147  return;
148  }
149  value = *(gint*)qof_collection_get_data(target);
150  if (value != 0)
151  {
152  return;
153  }
154  guid = qof_instance_get_guid(ent);
155  if (guid_equal(guid, guid_null()))
156  {
157  value = -1;
158  qof_collection_set_data(target, &value);
159  return;
160  }
161  g_return_if_fail (target->e_type == ent->e_type);
162  e = qof_collection_lookup_entity(target, guid);
163  if ( e == NULL )
164  {
165  value = 1;
166  qof_collection_set_data(target, &value);
167  return;
168  }
169  value = 0;
170  qof_collection_set_data(target, &value);
171 }
172 
173 gint
174 qof_collection_compare (QofCollection *target, QofCollection *merge)
175 {
176  gint value;
177 
178  value = 0;
179  if (!target && !merge)
180  {
181  return 0;
182  }
183  if (target == merge)
184  {
185  return 0;
186  }
187  if (!target && merge)
188  {
189  return -1;
190  }
191  if (target && !merge)
192  {
193  return 1;
194  }
195  if (target->e_type != merge->e_type)
196  {
197  return -1;
198  }
199  qof_collection_set_data(target, &value);
200  qof_collection_foreach(merge, collection_compare_cb, target);
201  value = *(gint*)qof_collection_get_data(target);
202  if (value == 0)
203  {
204  qof_collection_set_data(merge, &value);
205  qof_collection_foreach(target, collection_compare_cb, merge);
206  value = *(gint*)qof_collection_get_data(merge);
207  }
208  return value;
209 }
210 
211 QofInstance *
212 qof_collection_lookup_entity (const QofCollection *col, const GncGUID * guid)
213 {
214  QofInstance *ent;
215  g_return_val_if_fail (col, NULL);
216  if (guid == NULL) return NULL;
217  ent = static_cast<QofInstance*>(g_hash_table_lookup (col->hash_of_entities,
218  guid));
219  if (ent != NULL && qof_instance_get_destroying(ent)) return NULL;
220  return ent;
221 }
222 
223 QofCollection *
224 qof_collection_from_glist (QofIdType type, const GList *glist)
225 {
226  QofCollection *coll;
227  QofInstance *ent;
228  const GList *list;
229 
230  coll = qof_collection_new(type);
231  for (list = glist; list != NULL; list = list->next)
232  {
233  ent = QOF_INSTANCE(list->data);
234  if (FALSE == qof_collection_add_entity(coll, ent))
235  {
237  return NULL;
238  }
239  }
240  return coll;
241 }
242 
243 guint
244 qof_collection_count (const QofCollection *col)
245 {
246  guint c;
247 
248  c = g_hash_table_size(col->hash_of_entities);
249  return c;
250 }
251 
252 /* =============================================================== */
253 
254 gboolean
255 qof_collection_is_dirty (const QofCollection *col)
256 {
257  return col ? col->is_dirty : FALSE;
258 }
259 
260 void
261 qof_collection_mark_clean (QofCollection *col)
262 {
263  if (col)
264  {
265  col->is_dirty = FALSE;
266  }
267 }
268 
269 void
270 qof_collection_mark_dirty (QofCollection *col)
271 {
272  if (col)
273  {
274  col->is_dirty = TRUE;
275  }
276 }
277 
278 void
279 qof_collection_print_dirty (const QofCollection *col, gpointer dummy)
280 {
281  if (col->is_dirty)
282  printf("%s collection is dirty.\n", col->e_type);
283  qof_collection_foreach(col, (QofInstanceForeachCB)qof_instance_print_dirty, NULL);
284 }
285 
286 /* =============================================================== */
287 
288 gpointer
289 qof_collection_get_data (const QofCollection *col)
290 {
291  return col ? col->data : NULL;
292 }
293 
294 void
295 qof_collection_set_data (QofCollection *col, gpointer user_data)
296 {
297  if (col)
298  {
299  col->data = user_data;
300  }
301 }
302 
303 /* =============================================================== */
304 
305 void
306 qof_collection_foreach_sorted (const QofCollection *col, QofInstanceForeachCB cb_func,
307  gpointer user_data, GCompareFunc sort_fn)
308 {
309  GList *entries;
310 
311  g_return_if_fail (col);
312  g_return_if_fail (cb_func);
313 
314  PINFO("Hash Table size of %s before is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
315 
316  entries = g_hash_table_get_values (col->hash_of_entities);
317  if (sort_fn)
318  entries = g_list_sort (entries, sort_fn);
319  g_list_foreach (entries, (GFunc)cb_func, user_data);
320  g_list_free (entries);
321 
322  PINFO("Hash Table size of %s after is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
323 }
324 
325 void
326 qof_collection_foreach (const QofCollection *col, QofInstanceForeachCB cb_func,
327  gpointer user_data)
328 {
329  qof_collection_foreach_sorted (col, cb_func, user_data, nullptr);
330 }
331 /* =============================================================== */
const GncGUID * qof_instance_get_guid(gconstpointer inst)
Return the GncGUID of this instance.
gboolean qof_collection_is_dirty(const QofCollection *col)
Return value of &#39;dirty&#39; flag on collection.
Definition: qofid.cpp:255
QofInstance * qof_collection_lookup_entity(const QofCollection *col, const GncGUID *guid)
Find the entity going only from its guid.
Definition: qofid.cpp:212
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
gboolean qof_instance_get_destroying(gconstpointer ptr)
Retrieve the flag that indicates whether or not this object is about to be destroyed.
void(* QofInstanceForeachCB)(QofInstance *, gpointer user_data)
Callback type for qof_collection_foreach.
Definition: qofid.h:146
GHashTable * guid_hash_table_new(void)
Returns a GHashTable with <GUID*> as key and a <gpointer> as value and no destructor functions for ke...
Definition: guid.cpp:254
QofCollection * qof_instance_get_collection(gconstpointer ptr)
Return the collection this instance belongs to.
void qof_collection_foreach_sorted(const QofCollection *col, QofInstanceForeachCB cb_func, gpointer user_data, GCompareFunc sort_fn)
Call the callback for each entity in the collection.
Definition: qofid.cpp:306
gint qof_collection_compare(QofCollection *target, QofCollection *merge)
Compare two secondary collections.
Definition: qofid.cpp:174
const gchar * QofIdType
QofIdType declaration.
Definition: qofid.h:80
QofCollection * qof_collection_from_glist(QofIdType type, const GList *glist)
Create a secondary collection from a GList.
Definition: qofid.cpp:224
gboolean guid_equal(const GncGUID *guid_1, const GncGUID *guid_2)
Given two GUIDs, return TRUE if they are non-NULL and equal.
Definition: guid.cpp:204
void qof_collection_insert_entity(QofCollection *col, QofInstance *ent)
Take entity, remove it from whatever collection its currently in, and place it in a new collection...
Definition: qofid.cpp:95
void qof_collection_mark_clean(QofCollection *col)
reset value of dirty flag
Definition: qofid.cpp:261
void qof_collection_destroy(QofCollection *col)
destroy the collection
Definition: qofid.cpp:59
QofIdType qof_collection_get_type(const QofCollection *col)
return the type that the collection stores
Definition: qofid.cpp:73
QofIdType e_type
Entity type.
Definition: qofinstance.h:75
gboolean qof_collection_add_entity(QofCollection *coll, QofInstance *ent)
Add an entity to a QOF_TYPE_COLLECT.
Definition: qofid.cpp:109
const GncGUID * guid_null(void)
Returns a GncGUID which is guaranteed to never reference any entity.
Definition: guid.cpp:130
guint qof_collection_count(const QofCollection *col)
return the number of entities in the collection.
Definition: qofid.cpp:244
gpointer qof_collection_get_data(const QofCollection *col)
Store and retrieve arbitrary object-defined data.
Definition: qofid.cpp:289
The type used to store guids in C.
Definition: guid.h:75
QofCollection * qof_collection_new(QofIdType type)
create a new collection of entities of type
Definition: qofid.cpp:48