GnuCash  4.8a-132-gcdaeb421d+
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 extern "C"
28 {
29 #include <config.h>
30 #include <string.h>
31 }
32 
33 #include "qof.h"
34 #include "qofid-p.h"
35 #include "qofinstance-p.h"
36 
37 static QofLogModule log_module = QOF_MOD_ENGINE;
38 
40 {
41  QofIdType e_type;
42  gboolean is_dirty;
43 
44  GHashTable * hash_of_entities;
45  gpointer data; /* place where object class can hang arbitrary data */
46 };
47 
48 /* =============================================================== */
49 
50 QofCollection *
52 {
53  QofCollection *col;
54  col = g_new0(QofCollection, 1);
55  col->e_type = static_cast<QofIdType>(CACHE_INSERT (type));
56  col->hash_of_entities = guid_hash_table_new();
57  col->data = NULL;
58  return col;
59 }
60 
61 void
62 qof_collection_destroy (QofCollection *col)
63 {
64  CACHE_REMOVE (col->e_type);
65  g_hash_table_destroy(col->hash_of_entities);
66  col->e_type = NULL;
67  col->hash_of_entities = NULL;
68  col->data = NULL;
69  g_free (col);
70 }
71 
72 /* =============================================================== */
73 /* getters */
74 
76 qof_collection_get_type (const QofCollection *col)
77 {
78  return col->e_type;
79 }
80 
81 /* =============================================================== */
82 
83 void
84 qof_collection_remove_entity (QofInstance *ent)
85 {
86  QofCollection *col;
87  const GncGUID *guid;
88 
89  if (!ent) return;
90  col = qof_instance_get_collection(ent);
91  if (!col) return;
92  guid = qof_instance_get_guid(ent);
93  g_hash_table_remove (col->hash_of_entities, guid);
94  qof_instance_set_collection(ent, NULL);
95 }
96 
97 void
98 qof_collection_insert_entity (QofCollection *col, QofInstance *ent)
99 {
100  const GncGUID *guid;
101 
102  if (!col || !ent) return;
103  guid = qof_instance_get_guid(ent);
104  if (guid_equal(guid, guid_null())) return;
105  g_return_if_fail (col->e_type == ent->e_type);
106  qof_collection_remove_entity (ent);
107  g_hash_table_insert (col->hash_of_entities, (gpointer)guid, ent);
108  qof_instance_set_collection(ent, col);
109 }
110 
111 gboolean
112 qof_collection_add_entity (QofCollection *coll, QofInstance *ent)
113 {
114  QofInstance *e;
115  const GncGUID *guid;
116 
117  e = NULL;
118  if (!coll || !ent)
119  {
120  return FALSE;
121  }
122  guid = qof_instance_get_guid(ent);
123  if (guid_equal(guid, guid_null()))
124  {
125  return FALSE;
126  }
127  g_return_val_if_fail (coll->e_type == ent->e_type, FALSE);
128  e = qof_collection_lookup_entity(coll, guid);
129  if ( e != NULL )
130  {
131  return FALSE;
132  }
133  g_hash_table_insert (coll->hash_of_entities, (gpointer)guid, ent);
134  return TRUE;
135 }
136 
137 
138 static void
139 collection_compare_cb (QofInstance *ent, gpointer user_data)
140 {
141  QofCollection *target;
142  QofInstance *e;
143  const GncGUID *guid;
144  gint value;
145 
146  e = NULL;
147  target = (QofCollection*)user_data;
148  if (!target || !ent)
149  {
150  return;
151  }
152  value = *(gint*)qof_collection_get_data(target);
153  if (value != 0)
154  {
155  return;
156  }
157  guid = qof_instance_get_guid(ent);
158  if (guid_equal(guid, guid_null()))
159  {
160  value = -1;
161  qof_collection_set_data(target, &value);
162  return;
163  }
164  g_return_if_fail (target->e_type == ent->e_type);
165  e = qof_collection_lookup_entity(target, guid);
166  if ( e == NULL )
167  {
168  value = 1;
169  qof_collection_set_data(target, &value);
170  return;
171  }
172  value = 0;
173  qof_collection_set_data(target, &value);
174 }
175 
176 gint
177 qof_collection_compare (QofCollection *target, QofCollection *merge)
178 {
179  gint value;
180 
181  value = 0;
182  if (!target && !merge)
183  {
184  return 0;
185  }
186  if (target == merge)
187  {
188  return 0;
189  }
190  if (!target && merge)
191  {
192  return -1;
193  }
194  if (target && !merge)
195  {
196  return 1;
197  }
198  if (target->e_type != merge->e_type)
199  {
200  return -1;
201  }
202  qof_collection_set_data(target, &value);
203  qof_collection_foreach(merge, collection_compare_cb, target);
204  value = *(gint*)qof_collection_get_data(target);
205  if (value == 0)
206  {
207  qof_collection_set_data(merge, &value);
208  qof_collection_foreach(target, collection_compare_cb, merge);
209  value = *(gint*)qof_collection_get_data(merge);
210  }
211  return value;
212 }
213 
214 QofInstance *
215 qof_collection_lookup_entity (const QofCollection *col, const GncGUID * guid)
216 {
217  QofInstance *ent;
218  g_return_val_if_fail (col, NULL);
219  if (guid == NULL) return NULL;
220  ent = static_cast<QofInstance*>(g_hash_table_lookup (col->hash_of_entities,
221  guid));
222  return ent;
223 }
224 
225 QofCollection *
226 qof_collection_from_glist (QofIdType type, const GList *glist)
227 {
228  QofCollection *coll;
229  QofInstance *ent;
230  const GList *list;
231 
232  coll = qof_collection_new(type);
233  for (list = glist; list != NULL; list = list->next)
234  {
235  ent = QOF_INSTANCE(list->data);
236  if (FALSE == qof_collection_add_entity(coll, ent))
237  {
239  return NULL;
240  }
241  }
242  return coll;
243 }
244 
245 guint
246 qof_collection_count (const QofCollection *col)
247 {
248  guint c;
249 
250  c = g_hash_table_size(col->hash_of_entities);
251  return c;
252 }
253 
254 /* =============================================================== */
255 
256 gboolean
257 qof_collection_is_dirty (const QofCollection *col)
258 {
259  return col ? col->is_dirty : FALSE;
260 }
261 
262 void
263 qof_collection_mark_clean (QofCollection *col)
264 {
265  if (col)
266  {
267  col->is_dirty = FALSE;
268  }
269 }
270 
271 void
272 qof_collection_mark_dirty (QofCollection *col)
273 {
274  if (col)
275  {
276  col->is_dirty = TRUE;
277  }
278 }
279 
280 void
281 qof_collection_print_dirty (const QofCollection *col, gpointer dummy)
282 {
283  if (col->is_dirty)
284  printf("%s collection is dirty.\n", col->e_type);
285  qof_collection_foreach(col, (QofInstanceForeachCB)qof_instance_print_dirty, NULL);
286 }
287 
288 /* =============================================================== */
289 
290 gpointer
291 qof_collection_get_data (const QofCollection *col)
292 {
293  return col ? col->data : NULL;
294 }
295 
296 void
297 qof_collection_set_data (QofCollection *col, gpointer user_data)
298 {
299  if (col)
300  {
301  col->data = user_data;
302  }
303 }
304 
305 /* =============================================================== */
306 
308 {
310  gpointer data;
311 };
312 
313 static void
314 foreach_cb (gpointer item, gpointer arg)
315 {
316  struct _qofid_iterate *iter = static_cast<_qofid_iterate*>(arg);
317  QofInstance *ent = static_cast<QofInstance*>(item);
318 
319  iter->fcn (ent, iter->data);
320 }
321 
322 void
323 qof_collection_foreach (const QofCollection *col, QofInstanceForeachCB cb_func,
324  gpointer user_data)
325 {
326  struct _qofid_iterate iter;
327  GList *entries;
328 
329  g_return_if_fail (col);
330  g_return_if_fail (cb_func);
331 
332  iter.fcn = cb_func;
333  iter.data = user_data;
334 
335  PINFO("Hash Table size of %s before is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
336 
337  entries = g_hash_table_get_values (col->hash_of_entities);
338  g_list_foreach (entries, foreach_cb, &iter);
339  g_list_free (entries);
340 
341  PINFO("Hash Table size of %s after is %d", col->e_type, g_hash_table_size(col->hash_of_entities));
342 }
343 /* =============================================================== */
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:257
QofInstance * qof_collection_lookup_entity(const QofCollection *col, const GncGUID *guid)
Find the entity going only from its guid.
Definition: qofid.cpp:215
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
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:255
QofCollection * qof_instance_get_collection(gconstpointer ptr)
Return the collection this instance belongs to.
void qof_collection_foreach(const QofCollection *col, QofInstanceForeachCB cb_func, gpointer user_data)
Call the callback for each entity in the collection.
Definition: qofid.cpp:323
gint qof_collection_compare(QofCollection *target, QofCollection *merge)
Compare two secondary collections.
Definition: qofid.cpp:177
const gchar * QofIdType
QofIdType declaration.
Definition: qofid.h:85
QofCollection * qof_collection_from_glist(QofIdType type, const GList *glist)
Create a secondary collection from a GList.
Definition: qofid.cpp:226
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:98
void qof_collection_mark_clean(QofCollection *col)
reset value of dirty flag
Definition: qofid.cpp:263
void qof_collection_destroy(QofCollection *col)
destroy the collection
Definition: qofid.cpp:62
QofIdType qof_collection_get_type(const QofCollection *col)
return the type that the collection stores
Definition: qofid.cpp:76
gboolean qof_collection_add_entity(QofCollection *coll, QofInstance *ent)
Add an entity to a QOF_TYPE_COLLECT.
Definition: qofid.cpp:112
const GncGUID * guid_null(void)
Returns a GncGUID which is guaranteed to never reference any entity.
Definition: guid.cpp:131
guint qof_collection_count(const QofCollection *col)
return the number of entities in the collection.
Definition: qofid.cpp:246
gpointer qof_collection_get_data(const QofCollection *col)
Store and retrieve arbitrary object-defined data.
Definition: qofid.cpp:291
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:51