1 /*
2  * Copyright (C) 2008 - 2011 Murray Cumming <murrayc@murrayc.com>
3  * Copyright (C) 2008 - 2013 Vivien Malerba <malerba@gnome-db.org>
4  * Copyright (C) 2009 Bas Driessen <bas.driessen@xobas.com>
5  * Copyright (C) 2010 David King <davidk@openismus.com>
6  * Copyright (C) 2013 Daniel Espinosa <esodan@gmail.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
21  * Boston, MA  02110-1301, USA.
22  */
23 
24 #include <stdarg.h>
25 #include <string.h>
26 #ifdef HAVE_SYS_TYPES_H
27 #include <sys/types.h>
28 #endif
29 #include <glib/gi18n-lib.h>
30 #ifdef HAVE_LOCALE_H
31 #include <locale.h>
32 #endif
33 #include "gda-set.h"
34 #include "gda-marshal.h"
35 #include "gda-data-model.h"
36 #include "gda-data-model-import.h"
37 #include "gda-holder.h"
38 #include "gda-connection.h"
39 #include "gda-server-provider.h"
40 #include "gda-util.h"
41 #include <libgda/gda-custom-marshal.h>
42 #include <libgda/gda-types.h>
43 
44 extern xmlDtdPtr gda_paramlist_dtd;
45 extern gchar *gda_lang_locale;
46 
47 #ifdef GSEAL_ENABLE
48 /**
49  * GdaSetGroup:
50  * @nodes: (element-type Gda.SetNode): list of GdaSetNode, at least one entry
51  * @nodes_source: (allow-none):  if NULL, then @nodes contains exactly one entry
52  *
53  * Since 5.2, you must consider this struct as opaque. Any access to its internal must use public API.
54  * Don't try to use #gda_set_group_free on a struct that was created manually.
55  */
56 struct _GdaSetGroup {
57 	GSList       *nodes;       /* list of GdaSetNode, at least one entry */
58 	GdaSetSource *nodes_source; /* if NULL, then @nodes contains exactly one entry */
59 
60 	/*< private >*/
61 	/* Padding for future expansion */
62 	gpointer      _gda_reserved1;
63 	gpointer      _gda_reserved2;
64 };
65 #else
66 #endif
67 /*
68    Register GdaSetGroup type
69 */
70 GType
gda_set_group_get_type(void)71 gda_set_group_get_type (void)
72 {
73 	static GType type = 0;
74 
75 	if (G_UNLIKELY (type == 0)) {
76         if (type == 0)
77 			type = g_boxed_type_register_static ("GdaSetGroup",
78 							     (GBoxedCopyFunc) gda_set_group_copy,
79 							     (GBoxedFreeFunc) gda_set_group_free);
80 	}
81 
82 	return type;
83 }
84 
85 /**
86  * gda_set_group_new:
87  * @node: a #GdaSetNode struct
88  *
89  * Creates a new #GdaSetGroup struct. If @source is %NULL then new group contains
90  * just one #GdaSetNode.
91  *
92  * Return: (transfer full): a new #GdaSetGroup struct.
93  *
94  * Since: 5.2
95  */
96 GdaSetGroup*
gda_set_group_new(GdaSetNode * node)97 gda_set_group_new (GdaSetNode *node)
98 {
99 	GdaSetGroup *sg;
100 
101 	g_return_val_if_fail (node, NULL);
102 
103 	sg = g_new0 (GdaSetGroup, 1);
104 	sg->nodes_source = NULL;
105 	sg->nodes = NULL;
106 	sg->nodes = g_slist_append (sg->nodes, node);
107 	return sg;
108 }
109 
110 /**
111  * gda_set_group_copy:
112  * @sg: a #GdaSetGroup
113  *
114  * Copy constructor.
115  *
116  * Returns: a new #GdaSetGroup
117  *
118  * Since: 5.2
119  */
120 GdaSetGroup *
gda_set_group_copy(GdaSetGroup * sg)121 gda_set_group_copy (GdaSetGroup *sg)
122 {
123 	g_return_val_if_fail (sg, NULL);
124 
125 	GdaSetGroup *n;
126 	n = g_new0 (GdaSetGroup, 1);
127 	n->nodes_source = sg->nodes_source;
128 	n->nodes = g_slist_copy (sg->nodes);
129 	return n;
130 }
131 
132 /**
133  * gda_set_group_free:
134  * @sg: (allow-none): a #GdaSetGroup struct to free
135  *
136  * Frees any resources taken by @sg struct. If @sg is %NULL, then nothing happens.
137  *
138  * Since: 5.2
139  */
140 void
gda_set_group_free(GdaSetGroup * sg)141 gda_set_group_free (GdaSetGroup *sg)
142 {
143 	g_return_if_fail(sg);
144 	g_slist_free (sg->nodes);
145 	g_free (sg);
146 }
147 
148 /**
149  * gda_set_group_set_source:
150  * @sg: a #GdaSetGroup
151  * @source: a #GdaSetSource to set
152  *
153  * Since: 5.2
154  */
155 void
gda_set_group_set_source(GdaSetGroup * sg,GdaSetSource * source)156 gda_set_group_set_source (GdaSetGroup *sg, GdaSetSource *source)
157 {
158 	g_return_if_fail (sg);
159 	sg->nodes_source = source;
160 }
161 
162 /**
163  * gda_set_group_get_source:
164  * @sg: a #GdaSetGroup
165  *
166  * Returns: a #GdaSetSource. If %NULL then @sg contains just one element.
167  *
168  * Since: 5.2
169  */
170 GdaSetSource*
gda_set_group_get_source(GdaSetGroup * sg)171 gda_set_group_get_source      (GdaSetGroup *sg)
172 {
173 	g_return_val_if_fail (sg, NULL);
174 	return sg->nodes_source;
175 }
176 
177 /**
178  * gda_set_group_add_node:
179  * @sg: a #GdaSetGroup
180  * @node: a #GdaSetNode to set
181  *
182  * Since: 5.2
183  */
184 void
gda_set_group_add_node(GdaSetGroup * sg,GdaSetNode * node)185 gda_set_group_add_node (GdaSetGroup *sg, GdaSetNode *node)
186 {
187 	g_return_if_fail (sg);
188 	g_return_if_fail (node);
189 	sg->nodes = g_slist_append (sg->nodes, node);
190 }
191 
192 /**
193  * gda_set_group_get_node:
194  * @sg: a #GdaSetGroup
195  *
196  * This method always return first #GdaSetNode in @sg.
197  *
198  * Returns: first #GdaSetNode in @sg.
199  *
200  * Since: 5.2
201  */
202 GdaSetNode*
gda_set_group_get_node(GdaSetGroup * sg)203 gda_set_group_get_node (GdaSetGroup *sg)
204 {
205 	g_return_val_if_fail (sg, NULL);
206 	g_return_val_if_fail (sg->nodes, NULL);
207 	return GDA_SET_NODE (sg->nodes->data);
208 }
209 
210 /**
211  * gda_set_group_get_nodes:
212  * @sg: a #GdaSetGroup
213  *
214  * Returns a #GSList with the #GdaSetNode grouped by @sg. You must use
215  * #g_slist_free on returned list.
216  *
217  * Returns: (transfer none) (element-type Gda.SetNode): a #GSList with all nodes in @sg.
218  *
219  * Since: 5.2
220  */
221 GSList*
gda_set_group_get_nodes(GdaSetGroup * sg)222 gda_set_group_get_nodes (GdaSetGroup *sg)
223 {
224 	g_return_val_if_fail (sg, NULL);
225 	g_return_val_if_fail (sg->nodes, NULL);
226 	return sg->nodes;
227 }
228 
229 /**
230  * gda_set_group_get_n_nodes:
231  * @sg: a #GdaSetGroup
232  *
233  * Returns: number of nodes in @sg.
234  *
235  * Since: 5.2
236  */
237 gint
gda_set_group_get_n_nodes(GdaSetGroup * sg)238 gda_set_group_get_n_nodes (GdaSetGroup *sg)
239 {
240 	g_return_val_if_fail (sg, -1);
241 	return g_slist_length (sg->nodes);
242 }
243 
244 #ifdef GSEAL_ENABLE
245 /**
246  * GdaSetSource:
247  * @data_model: Can't be NULL
248  * @nodes: (element-type Gda.SetNode): list of #GdaSetNode for which source_model == @data_model
249  *
250  * Since 5.2, you must consider this struct as opaque. Any access to its internal must use public API.
251  * Don't try to use #gda_set_source_free on a struct that was created manually.
252  **/
253 struct _GdaSetSource {
254 	GdaDataModel   *data_model;   /* Can't be NULL */
255 	GSList         *nodes;        /* list of #GdaSetNode for which source_model == @data_model */
256 
257 	/*< private >*/
258 	/* Padding for future expansion */
259 	gpointer        _gda_reserved1;
260 	gpointer        _gda_reserved2;
261 	gpointer        _gda_reserved3;
262 	gpointer        _gda_reserved4;
263 };
264 #else
265 #endif
266 
267 /*
268    Register GdaSetSource type
269 */
270 GType
gda_set_source_get_type(void)271 gda_set_source_get_type (void)
272 {
273 	static GType type = 0;
274 
275 	if (G_UNLIKELY (type == 0)) {
276         if (type == 0)
277 			type = g_boxed_type_register_static ("GdaSetSource",
278 							     (GBoxedCopyFunc) gda_set_source_copy,
279 							     (GBoxedFreeFunc) gda_set_source_free);
280 	}
281 
282 	return type;
283 }
284 
285 /**
286  * gda_set_source_new:
287  * @model: a #GdaDataModel
288  *
289  * Creates a new #GdaSetSource struct.
290  *
291  * Return: (transfer full): a new #GdaSetSource struct.
292  *
293  * Since: 5.2
294  */
295 GdaSetSource*
gda_set_source_new(GdaDataModel * model)296 gda_set_source_new (GdaDataModel *model)
297 {
298 	g_return_val_if_fail (model != NULL && GDA_IS_DATA_MODEL (model), NULL);
299 	GdaSetSource *s = g_new0 (GdaSetSource, 1);
300 	s->nodes = NULL;
301 	s->data_model = g_object_ref (model);
302 
303 	return s;
304 }
305 
306 /**
307  * gda_set_source_copy:
308  * @s: a #GdaSetGroup
309  *
310  * Copy constructor.
311  *
312  * Returns: a new #GdaSetSource
313  *
314  * Since: 5.2
315  */
316 GdaSetSource *
gda_set_source_copy(GdaSetSource * s)317 gda_set_source_copy (GdaSetSource *s)
318 {
319 	GdaSetSource *n;
320 	g_return_val_if_fail (s, NULL);
321 	n = gda_set_source_new (gda_set_source_get_data_model (s));
322 	n->nodes = g_slist_copy (s->nodes);
323 	return n;
324 }
325 
326 /**
327  * gda_set_source_free:
328  * @s: (allow-none): a #GdaSetSource struct to free
329  *
330  * Frees any resources taken by @s struct. If @s is %NULL, then nothing happens.
331  *
332  * Since: 5.2
333  */
334 void
gda_set_source_free(GdaSetSource * s)335 gda_set_source_free (GdaSetSource *s)
336 {
337 	g_return_if_fail(s);
338 	g_object_unref (s->data_model);
339 	g_slist_free (s->nodes); /* FIXME: A source must own its nodes, then they must be freed here
340 										this leaves to others responsability free nodes BEFORE
341 										to free this source */
342 	g_free (s);
343 }
344 
345 /**
346  * gda_set_source_get_data_model:
347  * @s: a #GdaSetSource
348  *
349  * Returns: (transfer none): a #GdaDataModel used by @s
350  *
351  * Since: 5.2
352  */
353 GdaDataModel*
gda_set_source_get_data_model(GdaSetSource * s)354 gda_set_source_get_data_model (GdaSetSource *s)
355 {
356 	g_return_val_if_fail (s, NULL);
357 	return s->data_model;
358 }
359 
360 /**
361  * gda_set_source_set_data_model:
362  * @s: a #GdaSetSource struct to free
363  * @model: a #GdaDataModel
364  *
365  * Set a #GdaDataModel
366  *
367  * Since: 5.2
368  */
369 void
gda_set_source_set_data_model(GdaSetSource * s,GdaDataModel * model)370 gda_set_source_set_data_model (GdaSetSource *s, GdaDataModel *model)
371 {
372 	g_return_if_fail (s);
373 	g_return_if_fail (GDA_IS_DATA_MODEL (model));
374 	s->data_model = g_object_ref (model);
375 }
376 
377 /**
378  * gda_set_source_add_node:
379  * @s: a #GdaSetSource
380  * @node: a #GdaSetNode to add
381  *
382  * Set a #GdaDataModel
383  *
384  * Since: 5.2
385  */
386 void
gda_set_source_add_node(GdaSetSource * s,GdaSetNode * node)387 gda_set_source_add_node (GdaSetSource *s, GdaSetNode *node)
388 {
389 	g_return_if_fail (s);
390 	g_return_if_fail (node);
391 	s->nodes = g_slist_append (s->nodes, node);
392 }
393 
394 /**
395  * gda_set_source_get_nodes:
396  * @s: a #GdaSetSource
397  *
398  * Returns: (transfer none) (element-type Gda.SetNode): a list of #GdaSetNode structs
399  *
400  * Since: 5.2
401  */
402 GSList*
gda_set_source_get_nodes(GdaSetSource * s)403 gda_set_source_get_nodes (GdaSetSource *s)
404 {
405 	g_return_val_if_fail (s, NULL);
406 	g_return_val_if_fail (s->nodes, NULL);
407 	return s->nodes;
408 }
409 
410 /**
411  * gda_set_source_get_n_nodes:
412  * @s: a #GdaSetSource
413  *
414  * Returns: number of nodes in @sg.
415  *
416  * Since: 5.2
417  */
418 gint
gda_set_source_get_n_nodes(GdaSetSource * s)419 gda_set_source_get_n_nodes (GdaSetSource *s)
420 {
421 	g_return_val_if_fail (s, -1);
422 	return g_slist_length (s->nodes);
423 }
424 #ifdef GSEAL_ENABLE
425 /**
426  * GdaSetNode:
427  * @holder: a #GdaHolder. It can't be NULL
428  * @source_model: a #GdaDataModel. It could be NULL
429  * @source_column: a #gint with the number of column in @source_model
430  *
431  * Since 5.2, you must consider this struct as opaque. Any access to its internal must use public API.
432  * Don't try to use #gda_set_node_free on a struct that was created manually.
433  */
434 struct _GdaSetNode {
435 	GdaHolder    *holder;        /* Can't be NULL */
436 	GdaDataModel *source_model;  /* may be NULL */
437 	gint          source_column; /* unused if @source_model is NULL */
438 
439 	/*< private >*/
440 	/* Padding for future expansion */
441 	gpointer      _gda_reserved1;
442 	gpointer      _gda_reserved2;
443 };
444 #endif
445 /*
446    Register GdaSetNode type
447 */
448 GType
gda_set_node_get_type(void)449 gda_set_node_get_type (void)
450 {
451 	static GType type = 0;
452 
453 	if (G_UNLIKELY (type == 0)) {
454         if (type == 0)
455 			type = g_boxed_type_register_static ("GdaSetNode",
456 							     (GBoxedCopyFunc) gda_set_node_copy,
457 							     (GBoxedFreeFunc) gda_set_node_free);
458 	}
459 
460 	return type;
461 }
462 
463 /**
464  * gda_set_node_new:
465  * @holder: a #GdaHolder to used by new #GdaSetNode
466  *
467  * Creates a new #GdaSetNode struct.
468  *
469  * Return: (transfer full): a new #GdaSetNode struct.
470  *
471  * Since: 5.2
472  */
473 GdaSetNode*
gda_set_node_new(GdaHolder * holder)474 gda_set_node_new (GdaHolder *holder)
475 {
476 	g_return_val_if_fail (GDA_IS_HOLDER (holder), NULL);
477 	GdaSetNode *n = g_new0 (GdaSetNode, 1);
478 	n->holder = holder;
479 	n->source_model = NULL;
480 	return n;
481 }
482 
483 /**
484  * gda_set_node_copy:
485  * @node: a #GdaSetNode to copy from
486  *
487  * Copy constructor.
488  *
489  * Returns: a new #GdaSetNode
490  *
491  * Since: 5.2
492  */
493 GdaSetNode *
gda_set_node_copy(GdaSetNode * node)494 gda_set_node_copy (GdaSetNode *node)
495 {
496 	g_return_val_if_fail (node, NULL);
497 
498 	GdaSetNode *n;
499 	n = gda_set_node_new (gda_set_node_get_holder (node));
500 	gda_set_node_set_source_column (n, gda_set_node_get_source_column (node));
501 	gda_set_node_set_holder (n, gda_set_node_get_holder (node));
502 	gda_set_node_set_data_model (n, gda_set_node_get_data_model (node));
503 	return n;
504 }
505 
506 /**
507  * gda_set_node_free:
508  * @node: (allow-none): a #GdaSetNode struct to free
509  *
510  * Frees any resources taken by @node struct. If @node is %NULL, then nothing happens.
511  *
512  * Since: 5.2
513  */
514 void
gda_set_node_free(GdaSetNode * node)515 gda_set_node_free (GdaSetNode *node)
516 {
517 	if (node == NULL)
518 		return;
519 	g_free (node);
520 }
521 
522 /**
523  * gda_set_node_get_holder:
524  * @node: a #GdaSetNode struct to get holder from
525  *
526  * Returns: (transfer none): the #GdaHolder used by @node
527  *
528  * Since: 5.2
529  */
530 GdaHolder*
gda_set_node_get_holder(GdaSetNode * node)531 gda_set_node_get_holder (GdaSetNode *node)
532 {
533 	g_return_val_if_fail (node, NULL);
534 	return node->holder;
535 }
536 
537 /**
538  * gda_set_node_set_holder:
539  * @node: a #GdaSetNode struct to set holder to
540  *
541  * Set a #GdaHolder to @node.
542  *
543  * Since: 5.2
544  */
545 void
gda_set_node_set_holder(GdaSetNode * node,GdaHolder * holder)546 gda_set_node_set_holder (GdaSetNode *node, GdaHolder *holder)
547 {
548 	g_return_if_fail (node);
549 	g_return_if_fail (GDA_IS_HOLDER (holder));
550 	node->holder = holder;
551 }
552 
553 /**
554  * gda_set_node_get_data_model:
555  * @node: a #GdaSetNode struct to get holder from
556  *
557  * Returns: (transfer none): the #GdaDataModel used by @node
558  *
559  * Since: 5.2
560  */
561 GdaDataModel*
gda_set_node_get_data_model(GdaSetNode * node)562 gda_set_node_get_data_model (GdaSetNode *node)
563 {
564 	g_return_val_if_fail (node, NULL);
565 	return node->source_model;
566 }
567 
568 /**
569  * gda_set_node_set_data_model:
570  * @node: a #GdaSetNode struct to set data model to
571  * @model: (allow-none): a #GdaDataModel to be used by @node
572  *
573  * Set a #GdaDataModel to be used by @node. @model increment its reference
574  * counting when set. Internally referenced column number is set to first column
575  * in @model.
576  *
577  * Since: 5.2
578  */
579 void
gda_set_node_set_data_model(GdaSetNode * node,GdaDataModel * model)580 gda_set_node_set_data_model (GdaSetNode *node, GdaDataModel *model)
581 {
582 	g_return_if_fail (node);
583 	if (GDA_IS_DATA_MODEL (model)) {
584 		node->source_model = model;
585 		node->source_column = 0;
586 	}
587 	else {
588 		node->source_model = NULL;
589 		node->source_column = -1;
590 	}
591 }
592 
593 /**
594  * gda_set_node_get_source_column:
595  * @node: a #GdaSetNode struct to get column source from
596  *
597  * Returns: the number of column referenced in a given #GdaDataModel. If negative
598  * no column is referenced or no #GdaDataModel is used by @node.
599  *
600  * Since: 5.2
601  */
602 gint
gda_set_node_get_source_column(GdaSetNode * node)603 gda_set_node_get_source_column (GdaSetNode *node)
604 {
605 	g_return_val_if_fail (node, -1);
606 	return node->source_column;
607 }
608 
609 /**
610  * gda_set_node_set_source_column:
611  * @node: a #GdaSetNode struct to set column source to, from an used data model
612  *
613  * Set column number in the #GdaDataModel used @node. If no #GdaDataModel is set
614  * then column is set to invalid (-1);
615  *
616  * Since: 5.2
617  */
618 void
gda_set_node_set_source_column(GdaSetNode * node,gint column)619 gda_set_node_set_source_column (GdaSetNode *node, gint column)
620 {
621 	g_return_if_fail (column >= 0);
622 	if (GDA_IS_DATA_MODEL (node->source_model)) {
623 		if (column < gda_data_model_get_n_columns (node->source_model))
624 			node->source_column = column;
625 	}
626 }
627 
628 /*
629  * Main static functions
630  */
631 static void gda_set_class_init (GdaSetClass *class);
632 static void gda_set_init (GdaSet *set);
633 static void gda_set_dispose (GObject *object);
634 static void gda_set_finalize (GObject *object);
635 
636 static void set_remove_node (GdaSet *set, GdaSetNode *node);
637 static void set_remove_source (GdaSet *set, GdaSetSource *source);
638 
639 
640 static void changed_holder_cb (GdaHolder *holder, GdaSet *dataset);
641 static GError *validate_change_holder_cb (GdaHolder *holder, const GValue *value, GdaSet *dataset);
642 static void source_changed_holder_cb (GdaHolder *holder, GdaSet *dataset);
643 static void att_holder_changed_cb (GdaHolder *holder, const gchar *att_name, const GValue *att_value, GdaSet *dataset);
644 static void holder_notify_cb (GdaHolder *holder, GParamSpec *pspec, GdaSet *dataset);
645 
646 
647 static void compute_public_data (GdaSet *set);
648 static gboolean gda_set_real_add_holder (GdaSet *set, GdaHolder *holder);
649 
650 /* get a pointer to the parents to be able to call their destructor */
651 static GObjectClass  *parent_class = NULL;
652 
653 /* properties */
654 enum
655 {
656 	PROP_0,
657 	PROP_ID,
658 	PROP_NAME,
659 	PROP_DESCR,
660 	PROP_HOLDERS,
661 	PROP_VALIDATE_CHANGES
662 };
663 
664 /* signals */
665 enum
666 {
667 	HOLDER_CHANGED,
668 	PUBLIC_DATA_CHANGED,
669 	HOLDER_ATTR_CHANGED,
670 	VALIDATE_HOLDER_CHANGE,
671 	VALIDATE_SET,
672 	HOLDER_TYPE_SET,
673 	SOURCE_MODEL_CHANGED,
674 	LAST_SIGNAL
675 };
676 
677 static gint gda_set_signals[LAST_SIGNAL] = { 0, 0, 0, 0, 0, 0 };
678 
679 
680 /* private structure */
681 struct _GdaSetPrivate
682 {
683 	gchar           *id;
684 	gchar           *name;
685 	gchar           *descr;
686 	GHashTable      *holders_hash; /* key = GdaHoler ID, value = GdaHolder */
687 	GArray          *holders_array;
688 	gboolean         read_only;
689 	gboolean         validate_changes;
690 };
691 
692 static void
gda_set_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)693 gda_set_set_property (GObject *object,
694 		      guint param_id,
695 		      const GValue *value,
696 		      GParamSpec *pspec)
697 {
698 	GdaSet* set;
699 	set = GDA_SET (object);
700 
701 	switch (param_id) {
702 	case PROP_ID:
703 		g_free (set->priv->id);
704 		set->priv->id = g_value_dup_string (value);
705 		break;
706 	case PROP_NAME:
707 		g_free (set->priv->name);
708 		set->priv->name = g_value_dup_string (value);
709 		break;
710 	case PROP_DESCR:
711 		g_free (set->priv->descr);
712 		set->priv->descr = g_value_dup_string (value);
713 		break;
714 	case PROP_HOLDERS: {
715 		/* add the holders */
716 		GSList* holders;
717 		for (holders = (GSList*) g_value_get_pointer (value); holders; holders = holders->next)
718 			gda_set_real_add_holder (set, GDA_HOLDER (holders->data));
719 		compute_public_data (set);
720 		break;
721 	}
722 	case PROP_VALIDATE_CHANGES:
723 		if (set->priv->validate_changes != g_value_get_boolean (value)) {
724 			GSList *list;
725 			set->priv->validate_changes = g_value_get_boolean (value);
726 			for (list = set->holders; list; list = list->next) {
727 				GdaHolder *holder = (GdaHolder*) list->data;
728 				g_object_set ((GObject*) holder, "validate-changes",
729 					      set->priv->validate_changes, NULL);
730 				if (set->priv->validate_changes)
731 					g_signal_connect ((GObject*) holder, "validate-change",
732 							  G_CALLBACK (validate_change_holder_cb), set);
733 				else
734 					g_signal_handlers_disconnect_by_func ((GObject*) holder,
735 									      G_CALLBACK (validate_change_holder_cb),
736 									      set);
737 			}
738 		}
739 		break;
740 	default:
741 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
742 		break;
743 	}
744 }
745 
746 static void
gda_set_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)747 gda_set_get_property (GObject *object,
748 		      guint param_id,
749 		      GValue *value,
750 		      GParamSpec *pspec)
751 {
752 	GdaSet* set;
753 	set = GDA_SET (object);
754 
755 	switch (param_id) {
756 	case PROP_ID:
757 		g_value_set_string (value, set->priv->id);
758 		break;
759 	case PROP_NAME:
760 		if (set->priv->name)
761 			g_value_set_string (value, set->priv->name);
762 		else
763 			g_value_set_string (value, set->priv->id);
764 		break;
765 	case PROP_DESCR:
766 		g_value_set_string (value, set->priv->descr);
767 		break;
768 	case PROP_VALIDATE_CHANGES:
769 		g_value_set_boolean (value, set->priv->validate_changes);
770 		break;
771 	default:
772 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
773 		break;
774 	}
775 }
776 
777 /* module error */
gda_set_error_quark(void)778 GQuark gda_set_error_quark (void)
779 {
780 	static GQuark quark;
781 	if (!quark)
782 		quark = g_quark_from_static_string ("gda_set_error");
783 	return quark;
784 }
785 
786 
787 GType
gda_set_get_type(void)788 gda_set_get_type (void)
789 {
790 	static GType type = 0;
791 
792 	if (G_UNLIKELY (type == 0)) {
793 		static GMutex registering;
794 		static const GTypeInfo info = {
795 			sizeof (GdaSetClass),
796 			(GBaseInitFunc) NULL,
797 			(GBaseFinalizeFunc) NULL,
798 			(GClassInitFunc) gda_set_class_init,
799 			NULL,
800 			NULL,
801 			sizeof (GdaSet),
802 			0,
803 			(GInstanceInitFunc) gda_set_init,
804 			0
805 		};
806 
807 		g_mutex_lock (&registering);
808 		if (type == 0)
809 			type = g_type_register_static (G_TYPE_OBJECT, "GdaSet", &info, 0);
810 		g_mutex_unlock (&registering);
811 	}
812 
813 	return type;
814 }
815 
816 static gboolean
validate_accumulator(G_GNUC_UNUSED GSignalInvocationHint * ihint,GValue * return_accu,const GValue * handler_return,G_GNUC_UNUSED gpointer data)817 validate_accumulator (G_GNUC_UNUSED GSignalInvocationHint *ihint,
818 		      GValue *return_accu,
819 		      const GValue *handler_return,
820 		      G_GNUC_UNUSED gpointer data)
821 {
822 	GError *error;
823 
824 	error = g_value_get_boxed (handler_return);
825 	g_value_set_boxed (return_accu, error);
826 
827 	return error ? FALSE : TRUE; /* stop signal if an error has been set */
828 }
829 
830 static GError *
m_validate_holder_change(G_GNUC_UNUSED GdaSet * set,G_GNUC_UNUSED GdaHolder * holder,G_GNUC_UNUSED const GValue * new_value)831 m_validate_holder_change (G_GNUC_UNUSED GdaSet *set, G_GNUC_UNUSED GdaHolder *holder,
832 			  G_GNUC_UNUSED const GValue *new_value)
833 {
834 	return NULL;
835 }
836 
837 static GError *
m_validate_set(G_GNUC_UNUSED GdaSet * set)838 m_validate_set (G_GNUC_UNUSED GdaSet *set)
839 {
840 	return NULL;
841 }
842 
843 static void
gda_set_class_init(GdaSetClass * class)844 gda_set_class_init (GdaSetClass *class)
845 {
846 	GObjectClass   *object_class = G_OBJECT_CLASS (class);
847 
848 	parent_class = g_type_class_peek_parent (class);
849 
850 	gda_set_signals[HOLDER_CHANGED] =
851 		g_signal_new ("holder-changed",
852 			      G_TYPE_FROM_CLASS (object_class),
853 			      G_SIGNAL_RUN_FIRST,
854 			      G_STRUCT_OFFSET (GdaSetClass, holder_changed),
855 			      NULL, NULL,
856 			      _gda_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
857 			      GDA_TYPE_HOLDER);
858 
859 	/**
860 	 * GdaSet::validate-holder-change:
861 	 * @set: the #GdaSet
862 	 * @holder: the #GdaHolder which is going to change
863 	 * @new_value: the proposed new value for @holder
864 	 *
865 	 * Gets emitted when a #GdaHolder's in @set is going to change its value. One can connect to
866 	 * this signal to control which values @holder can have (for example to implement some business rules)
867 	 *
868 	 * Returns: NULL if @holder is allowed to change its value to @new_value, or a #GError
869 	 * otherwise.
870 	 */
871 	gda_set_signals[VALIDATE_HOLDER_CHANGE] =
872 		g_signal_new ("validate-holder-change",
873 			      G_TYPE_FROM_CLASS (object_class),
874 			      G_SIGNAL_RUN_LAST,
875 			      G_STRUCT_OFFSET (GdaSetClass, validate_holder_change),
876 			      validate_accumulator, NULL,
877 			      _gda_marshal_ERROR__OBJECT_VALUE, G_TYPE_ERROR, 2,
878 			      GDA_TYPE_HOLDER, G_TYPE_VALUE);
879 	/**
880 	 * GdaSet::validate-set:
881 	 * @set: the #GdaSet
882 	 *
883 	 * Gets emitted when gda_set_is_valid() is called, use
884 	 * this signal to control which combination of values @set's holder can have (for example to implement some business rules)
885 	 *
886 	 * Returns: NULL if @set's contents has been validated, or a #GError
887 	 * otherwise.
888 	 */
889 	gda_set_signals[VALIDATE_SET] =
890 		g_signal_new ("validate-set",
891 			      G_TYPE_FROM_CLASS (object_class),
892 			      G_SIGNAL_RUN_LAST,
893 			      G_STRUCT_OFFSET (GdaSetClass, validate_set),
894 			      validate_accumulator, NULL,
895 			      _gda_marshal_ERROR__VOID, G_TYPE_ERROR, 0);
896 	/**
897 	 * GdaSet::holder-attr-changed:
898 	 * @set: the #GdaSet
899 	 * @holder: the GdaHolder for which an attribute changed
900 	 * @attr_name: attribute's name
901 	 * @attr_value: attribute's value
902 	 *
903 	 * Gets emitted when an attribute for any of the #GdaHolder objects managed by @set has changed
904 	 */
905 	gda_set_signals[HOLDER_ATTR_CHANGED] =
906 		g_signal_new ("holder-attr-changed",
907 			      G_TYPE_FROM_CLASS (object_class),
908 			      G_SIGNAL_RUN_FIRST,
909 			      G_STRUCT_OFFSET (GdaSetClass, holder_attr_changed),
910 			      NULL, NULL,
911 			      _gda_marshal_VOID__OBJECT_STRING_VALUE, G_TYPE_NONE, 3,
912 			      GDA_TYPE_HOLDER, G_TYPE_STRING, G_TYPE_VALUE);
913 	/**
914 	 * GdaSet::public-data-changed:
915 	 * @set: the #GdaSet
916 	 *
917 	 * Gets emitted when @set's public data (#GdaSetNode, #GdaSetGroup or #GdaSetSource values) have changed
918 	 */
919 	gda_set_signals[PUBLIC_DATA_CHANGED] =
920 		g_signal_new ("public-data-changed",
921 			      G_TYPE_FROM_CLASS (object_class),
922 			      G_SIGNAL_RUN_FIRST,
923 			      G_STRUCT_OFFSET (GdaSetClass, public_data_changed),
924 			      NULL, NULL,
925 			      _gda_marshal_VOID__VOID, G_TYPE_NONE, 0);
926 
927 	/**
928 	 * GdaSet::holder-type-set:
929 	 * @set: the #GdaSet
930 	 * @holder: the #GdaHolder for which the #GType has been set
931 	 *
932 	 * Gets emitted when @holder in @set has its type finally set, in case
933 	 * it was #GDA_TYPE_NULL
934 	 *
935 	 * Since: 4.2
936 	 */
937 	gda_set_signals[HOLDER_TYPE_SET] =
938 		g_signal_new ("holder-type-set",
939 			      G_TYPE_FROM_CLASS (object_class),
940 			      G_SIGNAL_RUN_FIRST,
941 			      G_STRUCT_OFFSET (GdaSetClass, holder_type_set),
942 			      NULL, NULL,
943 			      _gda_marshal_VOID__OBJECT, G_TYPE_NONE, 1,
944 			      GDA_TYPE_HOLDER);
945 
946 	/**
947 	 * GdaSet::source-model-changed:
948 	 * @set: the #GdaSet
949 	 * @source: the #GdaSetSource for which the @data_model attribute has changed
950 	 *
951 	 * Gets emitted when the data model in @source has changed
952 	 *
953 	 * Since: 4.2
954 	 */
955 	gda_set_signals[SOURCE_MODEL_CHANGED] =
956 		g_signal_new ("source-model-changed",
957 			      G_TYPE_FROM_CLASS (object_class),
958 			      G_SIGNAL_RUN_FIRST,
959 			      G_STRUCT_OFFSET (GdaSetClass, source_model_changed),
960 			      NULL, NULL,
961 			      _gda_marshal_VOID__POINTER, G_TYPE_NONE, 1,
962 			      G_TYPE_POINTER);
963 
964 
965 	class->holder_changed = NULL;
966 	class->validate_holder_change = m_validate_holder_change;
967 	class->validate_set = m_validate_set;
968 	class->holder_attr_changed = NULL;
969 	class->public_data_changed = NULL;
970 	class->holder_type_set = NULL;
971 	class->source_model_changed = NULL;
972 
973 	/* Properties */
974 	object_class->set_property = gda_set_set_property;
975 	object_class->get_property = gda_set_get_property;
976 	g_object_class_install_property (object_class, PROP_ID,
977 					 g_param_spec_string ("id", NULL, "Id", NULL,
978 							      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
979 	g_object_class_install_property (object_class, PROP_NAME,
980 					 g_param_spec_string ("name", NULL, "Name", NULL,
981 							      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
982 	g_object_class_install_property (object_class, PROP_DESCR,
983 					 g_param_spec_string ("description", NULL, "Description", NULL,
984 							      (G_PARAM_READABLE | G_PARAM_WRITABLE)));
985 	g_object_class_install_property (object_class, PROP_HOLDERS,
986 					 g_param_spec_pointer ("holders", "GSList of GdaHolders",
987 							       "GdaHolder objects the set should contain", (
988 								G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)));
989 	/**
990 	 * GdaSet:validate-changes:
991 	 *
992 	 * Defines if the "validate-set" signal gets emitted when
993 	 * any holder in the data set changes. This property also affects the
994 	 * GdaHolder:validate-changes property.
995 	 *
996 	 * Since: 5.2.0
997 	 */
998 	g_object_class_install_property (object_class, PROP_VALIDATE_CHANGES,
999 					 g_param_spec_boolean ("validate-changes", NULL, "Defines if the validate-set signal is emitted", TRUE,
1000 							       (G_PARAM_READABLE | G_PARAM_WRITABLE)));
1001 	object_class->dispose = gda_set_dispose;
1002 	object_class->finalize = gda_set_finalize;
1003 }
1004 
1005 static void
gda_set_init(GdaSet * set)1006 gda_set_init (GdaSet *set)
1007 {
1008 	set->priv = g_new0 (GdaSetPrivate, 1);
1009 	set->holders = NULL;
1010 	set->nodes_list = NULL;
1011 	set->sources_list = NULL;
1012 	set->groups_list = NULL;
1013 	set->priv->holders_hash = g_hash_table_new (g_str_hash, g_str_equal);
1014 	set->priv->holders_array = NULL;
1015 	set->priv->read_only = FALSE;
1016 	set->priv->validate_changes = TRUE;
1017 }
1018 
1019 
1020 /**
1021  * gda_set_new:
1022  * @holders: (element-type Gda.Holder) (transfer none): a list of #GdaHolder objects
1023  *
1024  * Creates a new #GdaSet object, and populates it with the list given as argument.
1025  * The list can then be freed as it is copied. All the value holders in @holders are referenced counted
1026  * and modified, so they should not be used anymore afterwards.
1027  *
1028  * Returns: a new #GdaSet object
1029  */
1030 GdaSet *
gda_set_new(GSList * holders)1031 gda_set_new (GSList *holders)
1032 {
1033 	GObject *obj;
1034 
1035 	obj = g_object_new (GDA_TYPE_SET, NULL);
1036 	for (; holders; holders = holders->next)
1037 		gda_set_real_add_holder ((GdaSet*) obj, GDA_HOLDER (holders->data));
1038 	compute_public_data ((GdaSet*) obj);
1039 
1040 	return (GdaSet*) obj;
1041 }
1042 
1043 /**
1044  * gda_set_new_read_only:
1045  * @holders: (element-type Gda.Holder) (transfer none): a list of #GdaHolder objects
1046  *
1047  * Creates a new #GdaSet like gda_set_new(), but does not allow modifications to any of the #GdaHolder
1048  * object in @holders. This function is used for Libgda's database providers' implementation.
1049  *
1050  * Returns: a new #GdaSet object
1051  *
1052  * Since: 4.2
1053  */
1054 GdaSet *
gda_set_new_read_only(GSList * holders)1055 gda_set_new_read_only (GSList *holders)
1056 {
1057 	GObject *obj;
1058 
1059 	obj = g_object_new (GDA_TYPE_SET, NULL);
1060 	((GdaSet*) obj)->priv->read_only = TRUE;
1061 	for (; holders; holders = holders->next)
1062 		gda_set_real_add_holder ((GdaSet*) obj, GDA_HOLDER (holders->data));
1063 	compute_public_data ((GdaSet*) obj);
1064 
1065 	return (GdaSet*) obj;
1066 }
1067 
1068 /**
1069  * gda_set_copy:
1070  * @set: a #GdaSet object
1071  *
1072  * Creates a new #GdaSet object, copy of @set
1073  *
1074  * Returns: (transfer full): a new #GdaSet object
1075  */
1076 GdaSet *
gda_set_copy(GdaSet * set)1077 gda_set_copy (GdaSet *set)
1078 {
1079 	GdaSet *copy;
1080 	GSList *list, *holders = NULL;
1081 	g_return_val_if_fail (GDA_IS_SET (set), NULL);
1082 
1083 	for (list = set->holders; list; list = list->next)
1084 		holders = g_slist_prepend (holders, gda_holder_copy (GDA_HOLDER (list->data)));
1085 	holders = g_slist_reverse (holders);
1086 
1087 	copy = g_object_new (GDA_TYPE_SET, "holders", holders, NULL);
1088 	g_slist_foreach (holders, (GFunc) g_object_unref, NULL);
1089 	g_slist_free (holders);
1090 
1091 	return copy;
1092 }
1093 
1094 /**
1095  * gda_set_new_inline:
1096  * @nb: the number of value holders which will be contained in the new #GdaSet
1097  * @...: a serie of a (const gchar*) id, (GType) type, and value
1098  *
1099  * Creates a new #GdaSet containing holders defined by each triplet in ...
1100  * For each triplet (id, Glib type and value),
1101  * the value must be of the correct type (gchar * if type is G_STRING, ...)
1102  *
1103  * Note that this function is a utility function and that only a limited set of types are supported. Trying
1104  * to use an unsupported type will result in a warning, and the returned value holder holding a safe default
1105  * value.
1106  *
1107  * Returns: (transfer full): a new #GdaSet object
1108  */
1109 GdaSet *
gda_set_new_inline(gint nb,...)1110 gda_set_new_inline (gint nb, ...)
1111 {
1112 	GdaSet *set = NULL;
1113 	GSList *holders = NULL;
1114 	va_list ap;
1115 	gchar *id;
1116 	gint i;
1117 	gboolean allok = TRUE;
1118 
1119 	/* build the list of holders */
1120 	va_start (ap, nb);
1121 	for (i = 0; i < nb; i++) {
1122 		GType type;
1123 		GdaHolder *holder;
1124 		GValue *value;
1125 		GError *lerror = NULL;
1126 
1127 		id = va_arg (ap, char *);
1128 		type = va_arg (ap, GType);
1129 		holder = (GdaHolder *) g_object_new (GDA_TYPE_HOLDER, "g-type", type, "id", id, NULL);
1130 
1131 		value = gda_value_new (type);
1132 		if (type == G_TYPE_BOOLEAN)
1133 			g_value_set_boolean (value, va_arg (ap, int));
1134                 else if (type == G_TYPE_STRING)
1135 			g_value_set_string (value, va_arg (ap, gchar *));
1136                 else if (type == G_TYPE_OBJECT)
1137 			g_value_set_object (value, va_arg (ap, gpointer));
1138 		else if (type == G_TYPE_INT)
1139 			g_value_set_int (value, va_arg (ap, gint));
1140 		else if (type == G_TYPE_UINT)
1141 			g_value_set_uint (value, va_arg (ap, guint));
1142 		else if (type == GDA_TYPE_BINARY)
1143 			gda_value_set_binary (value, va_arg (ap, GdaBinary *));
1144 		else if (type == G_TYPE_INT64)
1145 			g_value_set_int64 (value, va_arg (ap, gint64));
1146 		else if (type == G_TYPE_UINT64)
1147 			g_value_set_uint64 (value, va_arg (ap, guint64));
1148 		else if (type == GDA_TYPE_SHORT)
1149 			gda_value_set_short (value, va_arg (ap, int));
1150 		else if (type == GDA_TYPE_USHORT)
1151 			gda_value_set_ushort (value, va_arg (ap, guint));
1152 		else if (type == G_TYPE_CHAR)
1153 			g_value_set_schar (value, va_arg (ap, gint));
1154 		else if (type == G_TYPE_UCHAR)
1155 			g_value_set_uchar (value, va_arg (ap, guint));
1156 		else if (type == G_TYPE_FLOAT)
1157 			g_value_set_float (value, va_arg (ap, double));
1158 		else if (type == G_TYPE_DOUBLE)
1159 			g_value_set_double (value, va_arg (ap, gdouble));
1160 		else if (type == GDA_TYPE_NUMERIC)
1161 			gda_value_set_numeric (value, va_arg (ap, GdaNumeric *));
1162 		else if (type == G_TYPE_DATE)
1163 			g_value_set_boxed (value, va_arg (ap, GDate *));
1164 		else if (type == G_TYPE_LONG)
1165 			g_value_set_long (value, va_arg (ap, glong));
1166 		else if (type == G_TYPE_ULONG)
1167 			g_value_set_ulong (value, va_arg (ap, gulong));
1168 		else if (type == G_TYPE_GTYPE)
1169 			g_value_set_gtype (value, va_arg(ap, GType));
1170 		else if (type == GDA_TYPE_TIMESTAMP)
1171 			gda_value_set_timestamp (value, va_arg(ap, GdaTimestamp *));
1172 		else if (type == GDA_TYPE_TIME)
1173 			gda_value_set_time (value, va_arg(ap, GdaTime *));
1174 		else {
1175 			g_warning (_("%s() does not handle values of type '%s'."),
1176 				   __FUNCTION__, g_type_name (type));
1177 			g_object_unref (holder);
1178 			allok = FALSE;
1179 			break;
1180 		}
1181 
1182 		if (!gda_holder_take_value (holder, value, &lerror)) {
1183 			g_warning (_("Unable to set holder's value: %s"),
1184 				   lerror && lerror->message ? lerror->message : _("No detail"));
1185 			if (lerror)
1186 				g_error_free (lerror);
1187 			g_object_unref (holder);
1188 			allok = FALSE;
1189 			break;
1190 		}
1191 		holders = g_slist_append (holders, holder);
1192         }
1193 	va_end (ap);
1194 
1195 	/* create the set */
1196 	if (allok)
1197 		set = gda_set_new (holders);
1198 	if (holders) {
1199 		g_slist_foreach (holders, (GFunc) g_object_unref, NULL);
1200 		g_slist_free (holders);
1201 	}
1202 	return set;
1203 }
1204 
1205 /**
1206  * gda_set_set_holder_value: (skip)
1207  * @set: a #GdaSet object
1208  * @error: (allow-none): a place to store errors, or %NULL
1209  * @holder_id: the ID of the holder to set the value
1210  * @...: value, of the correct type, depending on the requested holder's type (not NULL)
1211  *
1212  * Set the value of the #GdaHolder which ID is @holder_id to a specified value
1213  *
1214  * Returns: %TRUE if no error occurred and the value was set correctly
1215  */
1216 gboolean
gda_set_set_holder_value(GdaSet * set,GError ** error,const gchar * holder_id,...)1217 gda_set_set_holder_value (GdaSet *set, GError **error, const gchar *holder_id, ...)
1218 {
1219 	GdaHolder *holder;
1220 	va_list ap;
1221 	GValue *value;
1222 	GType type;
1223 
1224 	g_return_val_if_fail (GDA_IS_SET (set), FALSE);
1225 	g_return_val_if_fail (set->priv, FALSE);
1226 
1227 	holder = gda_set_get_holder (set, holder_id);
1228 	if (!holder) {
1229 		g_set_error (error, GDA_SET_ERROR, GDA_SET_HOLDER_NOT_FOUND_ERROR,
1230 			     _("GdaHolder with ID '%s' not found in set"), holder_id);
1231 		return FALSE;
1232 	}
1233 	type = gda_holder_get_g_type (holder);
1234 	va_start (ap, holder_id);
1235 	value = gda_value_new (type);
1236 	if (type == G_TYPE_BOOLEAN)
1237 		g_value_set_boolean (value, va_arg (ap, int));
1238 	else if (type == G_TYPE_STRING)
1239 		g_value_set_string (value, va_arg (ap, gchar *));
1240 	else if (type == G_TYPE_OBJECT)
1241 		g_value_set_object (value, va_arg (ap, gpointer));
1242 	else if (type == G_TYPE_INT)
1243 		g_value_set_int (value, va_arg (ap, gint));
1244 	else if (type == G_TYPE_UINT)
1245 		g_value_set_uint (value, va_arg (ap, guint));
1246 	else if (type == GDA_TYPE_BINARY)
1247 		gda_value_set_binary (value, va_arg (ap, GdaBinary *));
1248 	else if (type == G_TYPE_INT64)
1249 		g_value_set_int64 (value, va_arg (ap, gint64));
1250 	else if (type == G_TYPE_UINT64)
1251 		g_value_set_uint64 (value, va_arg (ap, guint64));
1252 	else if (type == GDA_TYPE_SHORT)
1253 		gda_value_set_short (value, va_arg (ap, int));
1254 	else if (type == GDA_TYPE_USHORT)
1255 		gda_value_set_ushort (value, va_arg (ap, guint));
1256 	else if (type == G_TYPE_CHAR)
1257 		g_value_set_schar (value, va_arg (ap, gint));
1258 	else if (type == G_TYPE_UCHAR)
1259 		g_value_set_uchar (value, va_arg (ap, guint));
1260 	else if (type == G_TYPE_FLOAT)
1261 		g_value_set_float (value, va_arg (ap, double));
1262 	else if (type == G_TYPE_DOUBLE)
1263 		g_value_set_double (value, va_arg (ap, gdouble));
1264 	else if (type == GDA_TYPE_NUMERIC)
1265 		gda_value_set_numeric (value, va_arg (ap, GdaNumeric *));
1266 	else if (type == G_TYPE_DATE)
1267 		g_value_set_boxed (value, va_arg (ap, GDate *));
1268 	else if (type == GDA_TYPE_TIMESTAMP)
1269 		gda_value_set_timestamp (value, va_arg (ap, GdaTimestamp*));
1270 	else if (type == GDA_TYPE_TIME)
1271 		gda_value_set_time (value, va_arg (ap, GdaTime*));
1272 	else if (type == G_TYPE_LONG)
1273 		g_value_set_long (value, va_arg (ap, glong));
1274 	else if (type == G_TYPE_ULONG)
1275 		g_value_set_ulong (value, va_arg (ap, gulong));
1276 	else if (type == G_TYPE_GTYPE)
1277 		g_value_set_gtype (value, va_arg (ap, GType));
1278 	else {
1279 		g_set_error (error, GDA_SET_ERROR, GDA_SET_IMPLEMENTATION_ERROR,
1280 			     _("%s() does not handle values of type '%s'."),
1281 			     __FUNCTION__, g_type_name (type));
1282 		va_end (ap);
1283 		return FALSE;
1284 	}
1285 
1286 	va_end (ap);
1287 	return gda_holder_take_value (holder, value, error);
1288 }
1289 
1290 /**
1291  * gda_set_get_holder_value:
1292  * @set: a #GdaSet object
1293  * @holder_id: the ID of the holder to set the value
1294  *
1295  * Get the value of the #GdaHolder which ID is @holder_id
1296  *
1297  * Returns: (allow-none) (transfer none): the requested GValue, or %NULL (see gda_holder_get_value())
1298  */
1299 const GValue *
gda_set_get_holder_value(GdaSet * set,const gchar * holder_id)1300 gda_set_get_holder_value (GdaSet *set, const gchar *holder_id)
1301 {
1302 	GdaHolder *holder;
1303 
1304 	g_return_val_if_fail (GDA_IS_SET (set), FALSE);
1305 	g_return_val_if_fail (set->priv, FALSE);
1306 
1307 	holder = gda_set_get_holder (set, holder_id);
1308 	if (holder)
1309 		return gda_holder_get_value (holder);
1310 	else
1311 		return NULL;
1312 }
1313 
1314 static void
xml_validity_error_func(void * ctx,const char * msg,...)1315 xml_validity_error_func (void *ctx, const char *msg, ...)
1316 {
1317         va_list args;
1318         gchar *str, *str2, *newerr;
1319 
1320         va_start (args, msg);
1321         str = g_strdup_vprintf (msg, args);
1322         va_end (args);
1323 
1324 	str2 = *((gchar **) ctx);
1325 
1326         if (str2) {
1327                 newerr = g_strdup_printf ("%s\n%s", str2, str);
1328                 g_free (str2);
1329         }
1330         else
1331                 newerr = g_strdup (str);
1332         g_free (str);
1333 
1334 	*((gchar **) ctx) = newerr;
1335 }
1336 
1337 /**
1338  * gda_set_new_from_spec_string:
1339  * @xml_spec: a string
1340  * @error: (allow-none): a place to store the error, or %NULL
1341  *
1342  * Creates a new #GdaSet object from the @xml_spec
1343  * specifications
1344  *
1345  * Returns: (transfer full): a new object, or %NULL if an error occurred
1346  */
1347 GdaSet *
gda_set_new_from_spec_string(const gchar * xml_spec,GError ** error)1348 gda_set_new_from_spec_string (const gchar *xml_spec, GError **error)
1349 {
1350 	xmlDocPtr doc;
1351 	xmlNodePtr root;
1352 	GdaSet *set;
1353 
1354 	/* string parsing */
1355 	doc = xmlParseMemory (xml_spec, strlen (xml_spec));
1356 	if (!doc)
1357 		return NULL;
1358 
1359 	{
1360                 /* doc validation */
1361                 xmlValidCtxtPtr validc;
1362                 int xmlcheck;
1363 		gchar *err_str = NULL;
1364 		xmlDtdPtr old_dtd = NULL;
1365 
1366                 validc = g_new0 (xmlValidCtxt, 1);
1367                 validc->userData = &err_str;
1368                 validc->error = xml_validity_error_func;
1369                 validc->warning = NULL;
1370 
1371                 xmlcheck = xmlDoValidityCheckingDefaultValue;
1372                 xmlDoValidityCheckingDefaultValue = 1;
1373 
1374                 /* replace the DTD with ours */
1375 		if (gda_paramlist_dtd) {
1376 			old_dtd = doc->intSubset;
1377 			doc->intSubset = gda_paramlist_dtd;
1378 		}
1379 
1380 #ifndef G_OS_WIN32
1381                 if (doc->intSubset && !xmlValidateDocument (validc, doc)) {
1382 			if (gda_paramlist_dtd)
1383 				doc->intSubset = old_dtd;
1384                         xmlFreeDoc (doc);
1385                         g_free (validc);
1386 
1387                         if (err_str) {
1388                                 g_set_error (error,
1389                                              GDA_SET_ERROR,
1390                                              GDA_SET_XML_SPEC_ERROR,
1391                                              "XML spec. does not conform to DTD:\n%s", err_str);
1392                                 g_free (err_str);
1393                         }
1394                         else
1395                                 g_set_error (error,
1396                                              GDA_SET_ERROR,
1397                                              GDA_SET_XML_SPEC_ERROR,
1398                                              "%s", "XML spec. does not conform to DTD");
1399 
1400                         xmlDoValidityCheckingDefaultValue = xmlcheck;
1401                         return NULL;
1402                 }
1403 #endif
1404 		if (gda_paramlist_dtd)
1405 			doc->intSubset = old_dtd;
1406                 xmlDoValidityCheckingDefaultValue = xmlcheck;
1407                 g_free (validc);
1408         }
1409 
1410 	/* doc is now non NULL */
1411 	root = xmlDocGetRootElement (doc);
1412 	if (strcmp ((gchar*)root->name, "data-set-spec") != 0){
1413 		g_set_error (error, GDA_SET_ERROR, GDA_SET_XML_SPEC_ERROR,
1414 			     _("Spec's root node != 'data-set-spec': '%s'"), root->name);
1415 		return NULL;
1416 	}
1417 
1418 	/* creating holders */
1419 	root = root->xmlChildrenNode;
1420 	while (xmlNodeIsText (root))
1421 		root = root->next;
1422 
1423 	set = gda_set_new_from_spec_node (root, error);
1424 	xmlFreeDoc(doc);
1425 	return set;
1426 }
1427 
1428 
1429 /**
1430  * gda_set_new_from_spec_node:
1431  * @xml_spec: a #xmlNodePtr for a &lt;parameters&gt; tag
1432  * @error: (allow-none): a place to store the error, or %NULL
1433  *
1434  * Creates a new #GdaSet object from the @xml_spec
1435  * specifications
1436  *
1437  * Returns: (transfer full): a new object, or %NULL if an error occurred
1438  */
1439 GdaSet *
gda_set_new_from_spec_node(xmlNodePtr xml_spec,GError ** error)1440 gda_set_new_from_spec_node (xmlNodePtr xml_spec, GError **error)
1441 {
1442 	GdaSet *set = NULL;
1443 	GSList *holders = NULL, *sources = NULL;
1444 	GSList *list;
1445 	const gchar *lang = gda_lang_locale;
1446 
1447 	xmlNodePtr cur;
1448 	gboolean allok = TRUE;
1449 	gchar *str;
1450 
1451 	if (strcmp ((gchar*)xml_spec->name, "parameters") != 0){
1452 		g_set_error (error, GDA_SET_ERROR, GDA_SET_XML_SPEC_ERROR,
1453 			     _("Missing node <parameters>: '%s'"), xml_spec->name);
1454 		return NULL;
1455 	}
1456 
1457 	/* Holders' sources, not mandatory: makes the @sources list */
1458 	cur = xml_spec->next;
1459 	while (cur && (xmlNodeIsText (cur) || strcmp ((gchar*)cur->name, "sources")))
1460 		cur = cur->next;
1461 	if (allok && cur && !strcmp ((gchar*)cur->name, "sources")){
1462 		for (cur = cur->xmlChildrenNode; (cur != NULL) && allok; cur = cur->next) {
1463 			if (xmlNodeIsText (cur))
1464 				continue;
1465 
1466 			if (!strcmp ((gchar*)cur->name, "gda_array")) {
1467 				GdaDataModel *model;
1468 				GSList *errors;
1469 
1470 				model = gda_data_model_import_new_xml_node (cur);
1471 				errors = gda_data_model_import_get_errors (GDA_DATA_MODEL_IMPORT (model));
1472 				if (errors) {
1473 					GError *err = (GError *) errors->data;
1474 					g_set_error (error, GDA_SET_ERROR, GDA_SET_XML_SPEC_ERROR,
1475 						     "%s", err->message);
1476 					g_object_unref (model);
1477 					model = NULL;
1478 					allok = FALSE;
1479 				}
1480 				else  {
1481 					sources = g_slist_prepend (sources, model);
1482 					str = (gchar*)xmlGetProp(cur, (xmlChar*) "name");
1483 					if (str)
1484 						g_object_set_data_full (G_OBJECT (model), "name", str, xmlFree);
1485 				}
1486 			}
1487 		}
1488 	}
1489 
1490 	/* holders */
1491 	for (cur = xml_spec->xmlChildrenNode; cur && allok; cur = cur->next) {
1492 		if (xmlNodeIsText (cur))
1493 			continue;
1494 
1495 		if (!strcmp ((gchar*)cur->name, "parameter")) {
1496 			GdaHolder *holder = NULL;
1497 			gchar *str, *id;
1498 			xmlChar *this_lang;
1499 			xmlChar *gdatype;
1500 
1501 			/* don't care about entries for the wrong locale */
1502 			this_lang = xmlGetProp(cur, (xmlChar*)"lang");
1503 			if (this_lang && strncmp ((gchar*)this_lang, lang, strlen ((gchar*)this_lang))) {
1504 				g_free (this_lang);
1505 				continue;
1506 			}
1507 
1508 			/* find if there is already a holder with the same ID */
1509 			id = (gchar*)xmlGetProp(cur, (xmlChar*)"id");
1510 			for (list = holders; list && !holder; list = list->next) {
1511 				str = (gchar *) gda_holder_get_id ((GdaHolder *) list->data);
1512 				if (str && id && !strcmp (str, id))
1513 					holder = (GdaHolder *) list->data;
1514 			}
1515 			if (id)
1516 				xmlFree (id);
1517 
1518 			if (holder && !this_lang) {
1519 				xmlFree (this_lang);
1520 				continue;
1521 			}
1522 			g_free (this_lang);
1523 
1524 
1525 			/* find data type and create GdaHolder */
1526 			gdatype = xmlGetProp (cur, BAD_CAST "gdatype");
1527 
1528 			if (!holder) {
1529 				GType gt;
1530 				gt = gdatype ? gda_g_type_from_string ((gchar *) gdatype) : G_TYPE_STRING;
1531 				if (gt == G_TYPE_INVALID)
1532 					gt = GDA_TYPE_NULL;
1533 				holder = (GdaHolder*) (g_object_new (GDA_TYPE_HOLDER,
1534 								     "g-type", gt,
1535 								     NULL));
1536 				holders = g_slist_append (holders, holder);
1537 			}
1538 			if (gdatype)
1539 				xmlFree (gdatype);
1540 
1541 			/* set holder's attributes */
1542 			if (! gda_utility_holder_load_attributes (holder, cur, sources, error))
1543 				allok = FALSE;
1544 		}
1545 	}
1546 
1547 	/* setting prepared new names from sources (models) */
1548 	for (list = sources; list; list = list->next) {
1549 		str = g_object_get_data (G_OBJECT (list->data), "newname");
1550 		if (str) {
1551 			g_object_set_data_full (G_OBJECT (list->data), "name", g_strdup (str), g_free);
1552 			g_object_set_data (G_OBJECT (list->data), "newname", NULL);
1553 		}
1554 		str = g_object_get_data (G_OBJECT (list->data), "newdescr");
1555 		if (str) {
1556 			g_object_set_data_full (G_OBJECT (list->data), "descr", g_strdup (str), g_free);
1557 			g_object_set_data (G_OBJECT (list->data), "newdescr", NULL);
1558 		}
1559 	}
1560 
1561 	/* holders' values, constraints: TODO */
1562 
1563 	/* GdaSet creation */
1564 	if (allok) {
1565 		xmlChar *prop;;
1566 		set = gda_set_new (holders);
1567 
1568 		prop = xmlGetProp(xml_spec, (xmlChar*)"id");
1569 		if (prop) {
1570 			set->priv->id = g_strdup ((gchar*)prop);
1571 			xmlFree (prop);
1572 		}
1573 		prop = xmlGetProp(xml_spec, (xmlChar*)"name");
1574 		if (prop) {
1575 			set->priv->name = g_strdup ((gchar*)prop);
1576 			xmlFree (prop);
1577 		}
1578 		prop = xmlGetProp(xml_spec, (xmlChar*)"descr");
1579 		if (prop) {
1580 			set->priv->descr = g_strdup ((gchar*)prop);
1581 			xmlFree (prop);
1582 		}
1583 	}
1584 
1585 	g_slist_foreach (holders, (GFunc) g_object_unref, NULL);
1586 	g_slist_free (holders);
1587 	g_slist_foreach (sources, (GFunc) g_object_unref, NULL);
1588 	g_slist_free (sources);
1589 
1590 	return set;
1591 }
1592 
1593 /**
1594  * gda_set_remove_holder:
1595  * @set: a #GdaSet object
1596  * @holder: the #GdaHolder to remove from @set
1597  *
1598  * Removes a #GdaHolder from the list of holders managed by @set
1599  */
1600 void
gda_set_remove_holder(GdaSet * set,GdaHolder * holder)1601 gda_set_remove_holder (GdaSet *set, GdaHolder *holder)
1602 {
1603 	GdaSetNode *node;
1604 	GdaDataModel *model;
1605 
1606 	g_return_if_fail (GDA_IS_SET (set));
1607 	g_return_if_fail (set->priv);
1608 	g_return_if_fail (g_slist_find (set->holders, holder));
1609 
1610 	if (set->priv->validate_changes)
1611 		g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
1612 						      G_CALLBACK (validate_change_holder_cb), set);
1613 	if (! set->priv->read_only) {
1614 		g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
1615 						      G_CALLBACK (changed_holder_cb), set);
1616 		g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
1617 						      G_CALLBACK (source_changed_holder_cb), set);
1618 		g_signal_handlers_disconnect_by_func (G_OBJECT (holder),
1619 						      G_CALLBACK (att_holder_changed_cb), set);
1620 	}
1621 	g_signal_handlers_disconnect_by_func (holder,
1622 					      G_CALLBACK (holder_notify_cb), set);
1623 
1624 	/* now destroy the GdaSetNode and the GdaSetSource if necessary */
1625 	node = gda_set_get_node (set, holder);
1626 	g_assert (node);
1627 	model = gda_set_node_get_data_model (node);
1628 	if (GDA_IS_DATA_MODEL (model)) {
1629 		GdaSetSource *source;
1630 		GSList *nodes;
1631 
1632 		source = gda_set_get_source_for_model (set, model);
1633 		g_assert (source);
1634 		nodes = gda_set_source_get_nodes (source);
1635 		g_assert (nodes);
1636 		if (! nodes->next)
1637 			set_remove_source (set, source);
1638 	}
1639 	set_remove_node (set, node);
1640 
1641 	set->holders = g_slist_remove (set->holders, holder);
1642 	g_hash_table_remove (set->priv->holders_hash, gda_holder_get_id (holder));
1643 	if (set->priv->holders_array) {
1644 		g_array_free (set->priv->holders_array, TRUE);
1645 		set->priv->holders_array = NULL;
1646 	}
1647 	g_object_unref (G_OBJECT (holder));
1648 }
1649 
1650 static void
source_changed_holder_cb(G_GNUC_UNUSED GdaHolder * holder,GdaSet * set)1651 source_changed_holder_cb (G_GNUC_UNUSED GdaHolder *holder, GdaSet *set)
1652 {
1653 	compute_public_data (set);
1654 }
1655 
1656 static void
att_holder_changed_cb(GdaHolder * holder,const gchar * att_name,const GValue * att_value,GdaSet * set)1657 att_holder_changed_cb (GdaHolder *holder, const gchar *att_name, const GValue *att_value, GdaSet *set)
1658 {
1659 #ifdef GDA_DEBUG_signal
1660 	g_print (">> 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1661 #endif
1662 	g_signal_emit (G_OBJECT (set), gda_set_signals[HOLDER_ATTR_CHANGED], 0, holder, att_name, att_value);
1663 #ifdef GDA_DEBUG_signal
1664 	g_print ("<< 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1665 #endif
1666 }
1667 
1668 static GError *
validate_change_holder_cb(GdaHolder * holder,const GValue * value,GdaSet * set)1669 validate_change_holder_cb (GdaHolder *holder, const GValue *value, GdaSet *set)
1670 {
1671 	/* signal the holder validate-change */
1672 	GError *error = NULL;
1673 	if (set->priv->read_only)
1674 		g_set_error (&error, GDA_SET_ERROR, GDA_SET_READ_ONLY_ERROR, "%s", _("Data set does not allow modifications"));
1675 	else {
1676 #ifdef GDA_DEBUG_signal
1677 		g_print (">> 'VALIDATE_HOLDER_CHANGE' from %s\n", __FUNCTION__);
1678 #endif
1679 		g_signal_emit (G_OBJECT (set), gda_set_signals[VALIDATE_HOLDER_CHANGE], 0, holder, value, &error);
1680 #ifdef GDA_DEBUG_signal
1681 		g_print ("<< 'VALIDATE_HOLDER_CHANGED' from %s\n", __FUNCTION__);
1682 #endif
1683 	}
1684 	return error;
1685 }
1686 
1687 static void
changed_holder_cb(GdaHolder * holder,GdaSet * set)1688 changed_holder_cb (GdaHolder *holder, GdaSet *set)
1689 {
1690 	/* signal the holder change */
1691 #ifdef GDA_DEBUG_signal
1692 	g_print (">> 'HOLDER_CHANGED' from %s\n", __FUNCTION__);
1693 #endif
1694 	g_signal_emit (G_OBJECT (set), gda_set_signals[HOLDER_CHANGED], 0, holder);
1695 #ifdef GDA_DEBUG_signal
1696 	g_print ("<< 'HOLDER_CHANGED' from %s\n", __FUNCTION__);
1697 #endif
1698 }
1699 
1700 static void
group_free(GdaSetGroup * group,G_GNUC_UNUSED gpointer data)1701 group_free (GdaSetGroup *group, G_GNUC_UNUSED gpointer data)
1702 {
1703 	gda_set_group_free (group);
1704 }
1705 
1706 static void
gda_set_dispose(GObject * object)1707 gda_set_dispose (GObject *object)
1708 {
1709 	GdaSet *set;
1710 	GSList *list;
1711 
1712 	g_return_if_fail (object != NULL);
1713 	g_return_if_fail (GDA_IS_SET (object));
1714 
1715 	set = GDA_SET (object);
1716 	/* free the holders list */
1717 	if (set->holders) {
1718 		for (list = set->holders; list; list = list->next) {
1719 			if (set->priv->validate_changes)
1720 				g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
1721 								      G_CALLBACK (validate_change_holder_cb), set);
1722 			if (! set->priv->read_only) {
1723 				g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
1724 								      G_CALLBACK (changed_holder_cb), set);
1725 				g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
1726 								      G_CALLBACK (source_changed_holder_cb), set);
1727 				g_signal_handlers_disconnect_by_func (G_OBJECT (list->data),
1728 								      G_CALLBACK (att_holder_changed_cb), set);
1729 			}
1730 			g_object_unref (list->data);
1731 		}
1732 		g_slist_free (set->holders);
1733 	}
1734 	if (set->priv->holders_hash) {
1735 		g_hash_table_destroy (set->priv->holders_hash);
1736 		set->priv->holders_hash = NULL;
1737 	}
1738 	if (set->priv->holders_array) {
1739 		g_array_free (set->priv->holders_array, TRUE);
1740 		set->priv->holders_array = NULL;
1741 	}
1742 
1743 	/* free the nodes if there are some */
1744 	while (set->nodes_list)
1745 		set_remove_node (set, GDA_SET_NODE (set->nodes_list->data));
1746 	while (set->sources_list)
1747 		set_remove_source (set, GDA_SET_SOURCE (set->sources_list->data));
1748 
1749 	g_slist_foreach (set->groups_list, (GFunc) group_free, NULL);
1750 	g_slist_free (set->groups_list);
1751 	set->groups_list = NULL;
1752 
1753 	/* parent class */
1754 	parent_class->dispose (object);
1755 }
1756 
1757 static void
gda_set_finalize(GObject * object)1758 gda_set_finalize (GObject *object)
1759 {
1760 	GdaSet *set;
1761 
1762 	g_return_if_fail (object != NULL);
1763 	g_return_if_fail (GDA_IS_SET (object));
1764 
1765 	set = GDA_SET (object);
1766 	if (set->priv) {
1767 		g_free (set->priv->id);
1768 		g_free (set->priv->name);
1769 		g_free (set->priv->descr);
1770 		g_free (set->priv);
1771 		set->priv = NULL;
1772 	}
1773 
1774 	/* parent class */
1775 	parent_class->finalize (object);
1776 }
1777 
1778 /*
1779  * Resets and computes set->nodes, and if some nodes already exist, they are previously discarded
1780  */
1781 static void
compute_public_data(GdaSet * set)1782 compute_public_data (GdaSet *set)
1783 {
1784 	GSList *list;
1785 	GdaSetNode *node;
1786 	GdaSetSource *source;
1787 	GdaSetGroup *group;
1788 	GHashTable *groups = NULL;
1789 
1790 	/*
1791 	 * Get rid of all the previous structures
1792 	 */
1793 	while (set->nodes_list)
1794 		set_remove_node (set, GDA_SET_NODE (set->nodes_list->data));
1795 	while (set->sources_list)
1796 		set_remove_source (set, GDA_SET_SOURCE (set->sources_list->data));
1797 
1798 	g_slist_foreach (set->groups_list, (GFunc) group_free, NULL);
1799 	g_slist_free (set->groups_list);
1800 	set->groups_list = NULL;
1801 
1802 	/*
1803 	 * Creation of the GdaSetNode structures
1804 	 */
1805 	for (list = set->holders; list; list = list->next) {
1806 		GdaHolder *holder = GDA_HOLDER (list->data);
1807 		gint col;
1808 		node = gda_set_node_new (holder);
1809 		gda_set_node_set_data_model (node, gda_holder_get_source_model (holder, &col));
1810 		gda_set_node_set_source_column (node, col);
1811 		set->nodes_list = g_slist_prepend (set->nodes_list, node);
1812 	}
1813 	set->nodes_list = g_slist_reverse (set->nodes_list);
1814 
1815 	/*
1816 	 * Creation of the GdaSetSource and GdaSetGroup structures
1817 	 */
1818 	for (list = set->nodes_list; list;list = list->next) {
1819 		node = GDA_SET_NODE (list->data);
1820 
1821 		/* source */
1822 		source = NULL;
1823 		if (gda_set_node_get_data_model (node)) {
1824 			source = gda_set_get_source_for_model (set, gda_set_node_get_data_model (node));
1825 			if (source)
1826 				gda_set_source_add_node (source, node);
1827 			else {
1828 				source = gda_set_source_new (gda_set_node_get_data_model (node));
1829 				gda_set_source_add_node (source, node);
1830 				set->sources_list = g_slist_prepend (set->sources_list, source);
1831 			}
1832 		}
1833 
1834 		/* group */
1835 		group = NULL;
1836 		if (gda_set_node_get_data_model (node) && groups)
1837 			group = g_hash_table_lookup (groups, gda_set_node_get_data_model (node));
1838 		if (group)
1839 			gda_set_group_add_node (group, node);
1840 		else {
1841 			group = gda_set_group_new (node);
1842 			gda_set_group_set_source (group, source);
1843 			set->groups_list = g_slist_prepend (set->groups_list, group);
1844 			if (gda_set_node_get_data_model (node)) {
1845 				if (!groups)
1846 					groups = g_hash_table_new (NULL, NULL); /* key = source model,
1847                                                                value = GdaSetGroup */
1848 				g_hash_table_insert (groups, gda_set_node_get_data_model (node), group);
1849 			}
1850 		}
1851 	}
1852 	set->groups_list = g_slist_reverse (set->groups_list);
1853 	if (groups)
1854 		g_hash_table_destroy (groups);
1855 
1856 #ifdef GDA_DEBUG_signal
1857         g_print (">> 'PUBLIC_DATA_CHANGED' from %p\n", set);
1858 #endif
1859 	g_signal_emit (set, gda_set_signals[PUBLIC_DATA_CHANGED], 0);
1860 #ifdef GDA_DEBUG_signal
1861         g_print ("<< 'PUBLIC_DATA_CHANGED' from %p\n", set);
1862 #endif
1863 }
1864 
1865 /**
1866  * gda_set_add_holder:
1867  * @set: a #GdaSet object
1868  * @holder: a #GdaHolder object
1869  *
1870  * Adds @holder to the list of holders managed within @set.
1871  *
1872  * NOTE: if @set already has a #GdaHolder with the same ID as @holder, then @holder
1873  * will not be added to the set (even if @holder's type or value is not the same as the
1874  * one already in @set).
1875  *
1876  * Returns: TRUE if @holder has been added to @set (and FALSE if it has not been added because there is another #GdaHolder
1877  * with the same ID)
1878  */
1879 gboolean
gda_set_add_holder(GdaSet * set,GdaHolder * holder)1880 gda_set_add_holder (GdaSet *set, GdaHolder *holder)
1881 {
1882 	gboolean added;
1883 	g_return_val_if_fail (GDA_IS_SET (set), FALSE);
1884 	g_return_val_if_fail (GDA_IS_HOLDER (holder), FALSE);
1885 
1886 	added = gda_set_real_add_holder (set, holder);
1887 	if (added)
1888 		compute_public_data (set);
1889 	return added;
1890 }
1891 
1892 static void
holder_notify_cb(GdaHolder * holder,GParamSpec * pspec,GdaSet * dataset)1893 holder_notify_cb (GdaHolder *holder, GParamSpec *pspec, GdaSet *dataset)
1894 {
1895 	GType gtype;
1896 	gtype = gda_holder_get_g_type (holder);
1897 	if (!strcmp (pspec->name, "g-type")) {
1898 		g_assert (gtype != GDA_TYPE_NULL);
1899 		g_signal_emit (dataset, gda_set_signals[HOLDER_TYPE_SET], 0, holder);
1900 	}
1901 	else if (!strcmp (pspec->name, "name")) {
1902 #ifdef GDA_DEBUG_signal
1903 	g_print (">> 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1904 #endif
1905 	g_signal_emit (G_OBJECT (dataset), gda_set_signals[HOLDER_ATTR_CHANGED], 0, holder,
1906 		       GDA_ATTRIBUTE_NAME, gda_holder_get_attribute (holder, GDA_ATTRIBUTE_NAME));
1907 #ifdef GDA_DEBUG_signal
1908 	g_print ("<< 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1909 #endif
1910 	}
1911 	else if (!strcmp (pspec->name, "description")) {
1912 #ifdef GDA_DEBUG_signal
1913 	g_print (">> 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1914 #endif
1915 	g_signal_emit (G_OBJECT (dataset), gda_set_signals[HOLDER_ATTR_CHANGED], 0, holder,
1916 		       GDA_ATTRIBUTE_DESCRIPTION, gda_holder_get_attribute (holder, GDA_ATTRIBUTE_DESCRIPTION));
1917 #ifdef GDA_DEBUG_signal
1918 	g_print ("<< 'HOLDER_ATTR_CHANGED' from %s\n", __FUNCTION__);
1919 #endif
1920 	}
1921 }
1922 
1923 static gboolean
gda_set_real_add_holder(GdaSet * set,GdaHolder * holder)1924 gda_set_real_add_holder (GdaSet *set, GdaHolder *holder)
1925 {
1926 	GdaHolder *similar;
1927 	const gchar *hid;
1928 
1929 	/*
1930 	 * try to find a similar holder in the set->holders:
1931 	 * a holder B is similar to a holder A if it has the same ID
1932 	 */
1933 	hid = gda_holder_get_id (holder);
1934 	if (!hid) {
1935 		g_warning (_("GdaHolder needs to have an ID"));
1936 		return FALSE;
1937 	}
1938 
1939 	similar = (GdaHolder*) g_hash_table_lookup (set->priv->holders_hash, hid);
1940 	if (!similar) {
1941 		/* really add @holder to the set */
1942 		set->holders = g_slist_append (set->holders, holder);
1943 		g_hash_table_insert (set->priv->holders_hash, (gchar*) hid, holder);
1944 		if (set->priv->holders_array) {
1945 			g_array_free (set->priv->holders_array, TRUE);
1946 			set->priv->holders_array = NULL;
1947 		}
1948 		g_object_ref (holder);
1949 		if (set->priv->validate_changes)
1950 			g_signal_connect (G_OBJECT (holder), "validate-change",
1951 					  G_CALLBACK (validate_change_holder_cb), set);
1952 		if (! set->priv->read_only) {
1953 			g_signal_connect (G_OBJECT (holder), "changed",
1954 					  G_CALLBACK (changed_holder_cb), set);
1955 			g_signal_connect (G_OBJECT (holder), "source-changed",
1956 					  G_CALLBACK (source_changed_holder_cb), set);
1957 			g_signal_connect (G_OBJECT (holder), "attribute-changed",
1958 					  G_CALLBACK (att_holder_changed_cb), set);
1959 		}
1960 		if (gda_holder_get_g_type (holder) == GDA_TYPE_NULL)
1961 			g_signal_connect (G_OBJECT (holder), "notify::g-type",
1962 					  G_CALLBACK (holder_notify_cb), set);
1963 		g_signal_connect (G_OBJECT (holder), "notify::name",
1964 				  G_CALLBACK (holder_notify_cb), set);
1965 		g_signal_connect (G_OBJECT (holder), "notify::description",
1966 				  G_CALLBACK (holder_notify_cb), set);
1967 		return TRUE;
1968 	}
1969 	else if (similar == holder)
1970 		return FALSE;
1971 	else {
1972 #ifdef GDA_DEBUG_NO
1973 		g_print ("In Set %p, Holder %p and %p are similar, keeping %p only\n", set, similar, holder, similar);
1974 #endif
1975 		return FALSE;
1976 	}
1977 }
1978 
1979 
1980 /**
1981  * gda_set_merge_with_set:
1982  * @set: a #GdaSet object
1983  * @set_to_merge: a #GdaSet object
1984  *
1985  * Add to @set all the holders of @set_to_merge.
1986  * Note1: only the #GdaHolder of @set_to_merge for which no holder in @set has the same ID are merged
1987  * Note2: all the #GdaHolder merged in @set are still used by @set_to_merge.
1988  */
1989 void
gda_set_merge_with_set(GdaSet * set,GdaSet * set_to_merge)1990 gda_set_merge_with_set (GdaSet *set, GdaSet *set_to_merge)
1991 {
1992 	GSList *holders;
1993 	g_return_if_fail (GDA_IS_SET (set));
1994 	g_return_if_fail (set_to_merge && GDA_IS_SET (set_to_merge));
1995 
1996 	for (holders = set_to_merge->holders; holders; holders = holders->next)
1997 		gda_set_real_add_holder (set, GDA_HOLDER (holders->data));
1998 	compute_public_data (set);
1999 }
2000 
2001 static void
set_remove_node(GdaSet * set,GdaSetNode * node)2002 set_remove_node (GdaSet *set, GdaSetNode *node)
2003 {
2004 	g_return_if_fail (g_slist_find (set->nodes_list, node));
2005 	gda_set_node_free (node);
2006 	set->nodes_list = g_slist_remove (set->nodes_list, node);
2007 }
2008 
2009 static void
set_remove_source(GdaSet * set,GdaSetSource * source)2010 set_remove_source (GdaSet *set, GdaSetSource *source)
2011 {
2012 	g_return_if_fail (g_slist_find (set->sources_list, source));
2013 	gda_set_source_free (source);
2014 	set->sources_list = g_slist_remove (set->sources_list, source);
2015 }
2016 
2017 /**
2018  * gda_set_is_valid:
2019  * @set: a #GdaSet object
2020  * @error: (allow-none): a place to store validation errors, or %NULL
2021  *
2022  * This method tells if all @set's #GdaHolder objects are valid, and if
2023  * they represent a valid combination of values, as defined by rules
2024  * external to Libgda: the "validate-set" signal is emitted and if none of the signal handlers return an
2025  * error, then the returned value is TRUE, otherwise the return value is FALSE as soon as a signal handler
2026  * returns an error.
2027  *
2028  * Returns: TRUE if the set is valid
2029  */
2030 gboolean
gda_set_is_valid(GdaSet * set,GError ** error)2031 gda_set_is_valid (GdaSet *set, GError **error)
2032 {
2033 	GSList *holders;
2034 
2035 	g_return_val_if_fail (GDA_IS_SET (set), FALSE);
2036 	g_return_val_if_fail (set->priv, FALSE);
2037 
2038 	for (holders = set->holders; holders; holders = holders->next) {
2039 		if (!gda_holder_is_valid (GDA_HOLDER (holders->data))) {
2040 			g_set_error (error, GDA_SET_ERROR, GDA_SET_INVALID_ERROR,
2041 				     "%s", _("One or more values are invalid"));
2042 			return FALSE;
2043 		}
2044 	}
2045 
2046 	return _gda_set_validate (set, error);
2047 }
2048 
2049 gboolean
_gda_set_validate(GdaSet * set,GError ** error)2050 _gda_set_validate (GdaSet *set, GError **error)
2051 {
2052 	/* signal the holder validate-set */
2053 	GError *lerror = NULL;
2054 #ifdef GDA_DEBUG_signal
2055 	g_print (">> 'VALIDATE_SET' from %s\n", __FUNCTION__);
2056 #endif
2057 	g_signal_emit (G_OBJECT (set), gda_set_signals[VALIDATE_SET], 0, &lerror);
2058 #ifdef GDA_DEBUG_signal
2059 	g_print ("<< 'VALIDATE_SET' from %s\n", __FUNCTION__);
2060 #endif
2061 	if (lerror) {
2062 		g_propagate_error (error, lerror);
2063 		return FALSE;
2064 	}
2065 	return TRUE;
2066 }
2067 
2068 
2069 /**
2070  * gda_set_get_holder:
2071  * @set: a #GdaSet object
2072  * @holder_id: the ID of the requested value holder
2073  *
2074  * Finds a #GdaHolder using its ID
2075  *
2076  * Returns: (transfer none): the requested #GdaHolder or %NULL
2077  */
2078 GdaHolder *
gda_set_get_holder(GdaSet * set,const gchar * holder_id)2079 gda_set_get_holder (GdaSet *set, const gchar *holder_id)
2080 {
2081 	g_return_val_if_fail (GDA_IS_SET (set), NULL);
2082 	g_return_val_if_fail (holder_id, NULL);
2083 
2084 	return (GdaHolder *) g_hash_table_lookup (set->priv->holders_hash, holder_id);
2085 }
2086 
2087 /**
2088  * gda_set_get_nth_holder:
2089  * @set: a #GdaSet object
2090  * @pos: the position of the requested #GdaHolder, starting at %0
2091  *
2092  * Finds a #GdaHolder using its position
2093  *
2094  * Returns: (transfer none): the requested #GdaHolder or %NULL
2095  *
2096  * Since: 4.2
2097  */
2098 GdaHolder *
gda_set_get_nth_holder(GdaSet * set,gint pos)2099 gda_set_get_nth_holder (GdaSet *set, gint pos)
2100 {
2101 	g_return_val_if_fail (GDA_IS_SET (set), NULL);
2102 	g_return_val_if_fail (pos >= 0, NULL);
2103 
2104 	if (! set->priv->holders_array) {
2105 		GSList *list;
2106 		set->priv->holders_array = g_array_sized_new (FALSE, FALSE, sizeof (GdaHolder*),
2107 							      g_slist_length (set->holders));
2108 		for (list = set->holders; list; list = list->next)
2109 			g_array_append_val (set->priv->holders_array, list->data);
2110 	}
2111 	if ((guint)pos >= set->priv->holders_array->len)
2112 		return NULL;
2113 	else
2114 		return g_array_index (set->priv->holders_array, GdaHolder*, pos);
2115 }
2116 
2117 /**
2118  * gda_set_get_node:
2119  * @set: a #GdaSet object
2120  * @holder: a #GdaHolder object
2121  *
2122  * Finds a #GdaSetNode holding information for @holder, don't modify the returned structure
2123  *
2124  * Returns: (transfer none): the requested #GdaSetNode or %NULL
2125  */
2126 GdaSetNode *
gda_set_get_node(GdaSet * set,GdaHolder * holder)2127 gda_set_get_node (GdaSet *set, GdaHolder *holder)
2128 {
2129 	GdaSetNode *retval = NULL;
2130 	GSList *list;
2131 
2132 	g_return_val_if_fail (GDA_IS_SET (set), NULL);
2133 	g_return_val_if_fail (set->priv, NULL);
2134 	g_return_val_if_fail (GDA_IS_HOLDER (holder), NULL);
2135 	/* FIXME: May is better to use holder's hash for better performance */
2136 	g_return_val_if_fail (g_slist_find (set->holders, holder), NULL);
2137 
2138 	for (list = set->nodes_list; list && !retval; list = list->next) {
2139 		GdaHolder *node_holder;
2140 		retval = GDA_SET_NODE (list->data);
2141 		node_holder = gda_set_node_get_holder (retval);
2142 		if (node_holder == holder) /* FIXME: May is better to compare holders ID */
2143 			break;
2144 		else
2145 			retval = NULL;
2146 	}
2147 	return retval;
2148 }
2149 
2150 /**
2151  * gda_set_get_source:
2152  * @set: a #GdaSet object
2153  * @holder: a #GdaHolder object
2154  *
2155  * Finds a #GdaSetSource which contains the #GdaDataModel restricting the possible values of
2156  * @holder, don't modify the returned structure.
2157  *
2158  * Returns: (transfer none): the requested #GdaSetSource or %NULL
2159  */
2160 GdaSetSource *
gda_set_get_source(GdaSet * set,GdaHolder * holder)2161 gda_set_get_source (GdaSet *set, GdaHolder *holder)
2162 {
2163 	GdaSetNode *node;
2164 	GdaDataModel *node_model;
2165 
2166 	node = gda_set_get_node (set, holder);
2167 	node_model = gda_set_node_get_data_model (node);
2168 	if (node && GDA_IS_DATA_MODEL (node_model))
2169 		return gda_set_get_source_for_model (set, node_model);
2170 	else
2171 		return NULL;
2172 }
2173 
2174 /**
2175  * gda_set_get_group:
2176  * @set: a #GdaSet object
2177  * @holder: a #GdaHolder object
2178  *
2179  * Finds a #GdaSetGroup which lists a  #GdaSetNode containing @holder,
2180  * don't modify the returned structure.
2181  *
2182  * Returns: (transfer none): the requested #GdaSetGroup or %NULL
2183  */
2184 GdaSetGroup *
gda_set_get_group(GdaSet * set,GdaHolder * holder)2185 gda_set_get_group (GdaSet *set, GdaHolder *holder)
2186 {
2187 	GdaSetNode *node;
2188 	GdaSetGroup *retval = NULL;
2189 	GSList *list, *sublist;
2190 	GdaHolder *node_holder;
2191 
2192 	g_return_val_if_fail (GDA_IS_SET (set), NULL);
2193 	g_return_val_if_fail (set->priv, NULL);
2194 	g_return_val_if_fail (GDA_IS_HOLDER (holder), NULL);
2195 	/* FIXME: May is better to use holder's hash for better performance */
2196 	g_return_val_if_fail (g_slist_find (set->holders, holder), NULL);
2197 
2198 	for (list = set->groups_list; list && !retval; list = list->next) {
2199 		retval = GDA_SET_GROUP (list->data);
2200 		sublist = gda_set_group_get_nodes (retval);
2201 		while (sublist && !retval) {
2202 			node = GDA_SET_NODE (sublist->data);
2203 			if (node) {
2204 				node_holder = gda_set_node_get_holder (node);
2205 				if (node_holder == holder) /* FIXME: May is better to compare holders ID */
2206 					break;
2207 				else {
2208 					sublist = g_slist_next (sublist);
2209 					retval = NULL;
2210 				}
2211 			}
2212 		}
2213 	}
2214 	return retval;
2215 }
2216 
2217 
2218 /**
2219  * gda_set_get_source_for_model:
2220  * @set: a #GdaSet object
2221  * @model: a #GdaDataModel object
2222  *
2223  * Finds the #GdaSetSource structure used in @set for which @model is a
2224  * the data model (the returned structure should not be modified).
2225  *
2226  * Returns: (transfer none): the requested #GdaSetSource pointer or %NULL.
2227  */
2228 GdaSetSource *
gda_set_get_source_for_model(GdaSet * set,GdaDataModel * model)2229 gda_set_get_source_for_model (GdaSet *set, GdaDataModel *model)
2230 {
2231 	GdaSetSource *retval = NULL;
2232 	GdaDataModel *source_model;
2233 	GSList *list;
2234 
2235 	g_return_val_if_fail (GDA_IS_SET (set), NULL);
2236 	g_return_val_if_fail (set->priv, NULL);
2237 	g_return_val_if_fail (GDA_IS_DATA_MODEL (model), NULL);
2238 
2239 	list = set->sources_list;
2240 	while (list && !retval) {
2241 		retval = GDA_SET_SOURCE (list->data);
2242 		source_model = gda_set_source_get_data_model (retval);
2243 		if (GDA_IS_DATA_MODEL (source_model)) {
2244 			if (source_model == model)
2245 				break;
2246 			else
2247 				retval = NULL;
2248 		}
2249 		list = g_slist_next (list);
2250 	}
2251 
2252 	return retval;
2253 }
2254 
2255 /**
2256  * gda_set_replace_source_model:
2257  * @set: a #GdaSet object
2258  * @source: a pointer to a #GdaSetSource in @set
2259  * @model: a #GdaDataModel
2260  *
2261  * Replaces @source->data_model with @model, which must have the same
2262  * characteristics as @source->data_model (same column types)
2263  *
2264  * Also for each #GdaHolder for which @source->data_model is a source model,
2265  * this method calls gda_holder_set_source_model() with @model to replace
2266  * the source by the new model
2267  *
2268  * Since: 4.2
2269  */
2270 void
gda_set_replace_source_model(GdaSet * set,GdaSetSource * source,GdaDataModel * model)2271 gda_set_replace_source_model (GdaSet *set, GdaSetSource *source, GdaDataModel *model)
2272 {
2273 	GdaDataModel *source_model;
2274 
2275 	g_return_if_fail (GDA_IS_SET (set));
2276 	g_return_if_fail (source);
2277 	g_return_if_fail (g_slist_find (set->sources_list, source));
2278 	g_return_if_fail (GDA_IS_DATA_MODEL (model));
2279 
2280 	/* compare models */
2281 	gint ncols, i;
2282 
2283 	source_model = gda_set_source_get_data_model (source);
2284 	if (GDA_IS_DATA_MODEL (source_model)) {
2285 		ncols = gda_data_model_get_n_columns (source_model);
2286 		/* FIXME: This way to compare two Data Models could be useful as a function
2287 		 * gda_data_model_compare (GdaDataModel)
2288 		 **/
2289 		if (ncols != gda_data_model_get_n_columns (model)) {
2290 			g_warning (_("Replacing data model must have the same characteristics as the "
2291 					 "data model it replaces"));
2292 			return;
2293 		}
2294 		for (i = 0; i < ncols; i++) {
2295 			GdaColumn *c1, *c2;
2296 			GType t1, t2;
2297 			c1 = gda_data_model_describe_column (source->data_model, i);
2298 			c2 = gda_data_model_describe_column (model, i);
2299 			t1 = gda_column_get_g_type (c1);
2300 			t2 = gda_column_get_g_type (c2);
2301 
2302 			if ((t1 != GDA_TYPE_NULL) && (t2 != GDA_TYPE_NULL) && (t1 != t2)) {
2303 				g_warning (_("Replacing data model must have the same characteristics as the "
2304 						 "data model it replaces"));
2305 				return;
2306 			}
2307 		}
2308 	}
2309 
2310 	/* actually swap the models */
2311 	GSList *list;
2312 	gda_set_source_set_data_model (source, model);
2313 	for (list = gda_set_source_get_nodes (source); list; list = list->next) {
2314 		GdaSetNode *node = GDA_SET_NODE (list->data);
2315 		gda_set_node_set_data_model (node, model);
2316 		g_signal_handlers_block_by_func (G_OBJECT (node->holder),
2317 						 G_CALLBACK (source_changed_holder_cb), set);
2318 		gda_holder_set_source_model (GDA_HOLDER (node->holder), model, node->source_column,
2319 					     NULL);
2320 		g_signal_handlers_unblock_by_func (G_OBJECT (node->holder),
2321 						   G_CALLBACK (source_changed_holder_cb), set);
2322 
2323 	}
2324 #ifdef GDA_DEBUG_signal
2325 	g_print (">> 'SOURCE_MODEL_CHANGED' from %s\n", __FUNCTION__);
2326 #endif
2327 	g_signal_emit (G_OBJECT (set), gda_set_signals[SOURCE_MODEL_CHANGED], 0, source);
2328 #ifdef GDA_DEBUG_signal
2329 	g_print ("<< 'SOURCE_MODEL_CHANGED' from %s\n", __FUNCTION__);
2330 #endif
2331 }
2332 
2333 #ifdef GDA_DEBUG_NO
2334 static void holder_dump (GdaHolder *holder);
2335 static void set_node_dump (GdaSetNode *node);
2336 static void set_source_dump (GdaSetSource *source);
2337 static void set_group_dump (GdaSetGroup *group);
2338 
2339 static void
holder_dump(GdaHolder * holder)2340 holder_dump (GdaHolder *holder)
2341 {
2342 	g_print ("  GdaHolder %p (%s)\n", holder, holder ? gda_holder_get_id (holder) : "---");
2343 }
2344 
2345 static void
set_source_dump(GdaSetSource * source)2346 set_source_dump (GdaSetSource *source)
2347 {
2348 	g_print ("  GdaSetSource %p\n", source);
2349 	if (source) {
2350 		g_print ("    - data_model: %p\n", source->data_model);
2351 		GSList *list;
2352 		for (list = source->nodes; list; list = list->next)
2353 			g_print ("    - node: %p\n", list->data);
2354 	}
2355 }
2356 
2357 static void
set_group_dump(GdaSetGroup * group)2358 set_group_dump (GdaSetGroup *group)
2359 {
2360 	g_print ("  GdaSetGroup %p\n", group);
2361 	if (group) {
2362 		GSList *list;
2363 		for (list = gda_set_group_get_nodes (group); list; list = list->next)
2364 			g_print ("    - node: %p\n", list->data);
2365 		g_print ("    - GdaSetSource: %p\n", group->nodes_source);
2366 	}
2367 }
2368 
2369 static void
set_node_dump(GdaSetNode * node)2370 set_node_dump (GdaSetNode *node)
2371 {
2372 	g_print ("  GdaSetNode: %p\n", node);
2373 	g_print ("   - holder: %p (%s)\n", node->holder, node->holder ? gda_holder_get_id (node->holder) : "ERROR : no GdaHolder!");
2374 	g_print ("   - source_model: %p\n", node->source_model);
2375 	g_print ("   - source_column: %d\n", node->source_column);
2376 }
2377 
2378 void
gda_set_dump(GdaSet * set)2379 gda_set_dump (GdaSet *set)
2380 {
2381 	g_print ("=== GdaSet %p ===\n", set);
2382 	g_slist_foreach (set->holders, (GFunc) holder_dump, NULL);
2383 	g_slist_foreach (set->nodes_list, (GFunc) set_node_dump, NULL);
2384 	g_slist_foreach (set->sources_list, (GFunc) set_source_dump, NULL);
2385 	g_slist_foreach (set->groups_list, (GFunc) set_group_dump, NULL);
2386 	g_print ("=== GdaSet %p END ===\n", set);
2387 }
2388 #endif
2389