3
* Copyright (C) 2003 Vivien Malerba
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License as
7
* published by the Free Software Foundation; either version 2 of the
8
* License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21
#include "mg-qf-all.h"
22
#include "mg-xml-storage.h"
24
#include "mg-entity.h"
25
#include "mg-renderer.h"
26
#include "mg-referer.h"
27
#include "mg-ref-base.h"
30
#include "mg-target.h"
34
* Main static functions
36
static void mg_qf_all_class_init (MgQfAllClass * class);
37
static void mg_qf_all_init (MgQfAll *qf);
38
static void mg_qf_all_dispose (GObject *object);
39
static void mg_qf_all_finalize (GObject *object);
41
static void mg_qf_all_set_property (GObject *object,
45
static void mg_qf_all_get_property (GObject *object,
50
/* XML storage interface */
51
static void mg_qf_all_xml_storage_init (MgXmlStorageIface *iface);
52
static gchar *mg_qf_all_get_xml_id (MgXmlStorage *iface);
53
static xmlNodePtr mg_qf_all_save_to_xml (MgXmlStorage *iface, GError **error);
54
static gboolean mg_qf_all_load_from_xml (MgXmlStorage *iface, xmlNodePtr node, GError **error);
57
static void mg_qf_all_field_init (MgFieldIface *iface);
58
static MgEntity *mg_qf_all_get_entity (MgField *iface);
59
static MgServerDataType *mg_qf_all_get_data_type (MgField *iface);
61
/* Renderer interface */
62
static void mg_qf_all_renderer_init (MgRendererIface *iface);
63
static GdaXqlItem *mg_qf_all_render_as_xql (MgRenderer *iface, MgContext *context, GError **error);
64
static gchar *mg_qf_all_render_as_sql (MgRenderer *iface, MgContext *context, guint options, GError **error);
65
static gchar *mg_qf_all_render_as_str (MgRenderer *iface, MgContext *context);
67
/* Referer interface */
68
static void mg_qf_all_referer_init (MgRefererIface *iface);
69
static gboolean mg_qf_all_activate (MgReferer *iface);
70
static void mg_qf_all_deactivate (MgReferer *iface);
71
static gboolean mg_qf_all_is_active (MgReferer *iface);
72
static GSList *mg_qf_all_get_ref_objects (MgReferer *iface);
73
static void mg_qf_all_replace_refs (MgReferer *iface, GHashTable *replacements);
75
/* virtual functions */
76
static GObject *mg_qf_all_copy (MgQfield *orig);
77
static gboolean mg_qf_all_is_equal (MgQfield *qfield1, MgQfield *qfield2);
80
/* When the MgQuery or MgTarget is nullified */
81
static void nullified_object_cb (GObject *obj, MgQfAll *field);
84
static void mg_qf_all_dump (MgQfAll *field, guint offset);
87
/* get a pointer to the parents to be able to call their destructor */
88
static GObjectClass *parent_class = NULL;
97
static gint mg_qf_all_signals[LAST_SIGNAL] = { 0 };
107
/* private structure */
108
struct _MgQfAllPrivate
111
MgRefBase *target_ref;
116
GQuark mg_qf_all_error_quark (void)
120
quark = g_quark_from_static_string ("mg_qf_all_error");
126
mg_qf_all_get_type (void)
128
static GType type = 0;
131
static const GTypeInfo info = {
132
sizeof (MgQfAllClass),
133
(GBaseInitFunc) NULL,
134
(GBaseFinalizeFunc) NULL,
135
(GClassInitFunc) mg_qf_all_class_init,
140
(GInstanceInitFunc) mg_qf_all_init
143
static const GInterfaceInfo xml_storage_info = {
144
(GInterfaceInitFunc) mg_qf_all_xml_storage_init,
149
static const GInterfaceInfo field_info = {
150
(GInterfaceInitFunc) mg_qf_all_field_init,
155
static const GInterfaceInfo renderer_info = {
156
(GInterfaceInitFunc) mg_qf_all_renderer_init,
161
static const GInterfaceInfo referer_info = {
162
(GInterfaceInitFunc) mg_qf_all_referer_init,
168
type = g_type_register_static (MG_QFIELD_TYPE, "MgQfAll", &info, 0);
169
g_type_add_interface_static (type, MG_XML_STORAGE_TYPE, &xml_storage_info);
170
g_type_add_interface_static (type, MG_FIELD_TYPE, &field_info);
171
g_type_add_interface_static (type, MG_RENDERER_TYPE, &renderer_info);
172
g_type_add_interface_static (type, MG_REFERER_TYPE, &referer_info);
178
mg_qf_all_xml_storage_init (MgXmlStorageIface *iface)
180
iface->get_xml_id = mg_qf_all_get_xml_id;
181
iface->save_to_xml = mg_qf_all_save_to_xml;
182
iface->load_from_xml = mg_qf_all_load_from_xml;
186
mg_qf_all_field_init (MgFieldIface *iface)
188
iface->get_entity = mg_qf_all_get_entity;
189
iface->get_data_type = mg_qf_all_get_data_type;
193
mg_qf_all_renderer_init (MgRendererIface *iface)
195
iface->render_as_xql = mg_qf_all_render_as_xql;
196
iface->render_as_sql = mg_qf_all_render_as_sql;
197
iface->render_as_str = mg_qf_all_render_as_str;
198
iface->is_valid = NULL;
202
mg_qf_all_referer_init (MgRefererIface *iface)
204
iface->activate = mg_qf_all_activate;
205
iface->deactivate = mg_qf_all_deactivate;
206
iface->is_active = mg_qf_all_is_active;
207
iface->get_ref_objects = mg_qf_all_get_ref_objects;
208
iface->replace_refs = mg_qf_all_replace_refs;
212
mg_qf_all_class_init (MgQfAllClass * class)
214
GObjectClass *object_class = G_OBJECT_CLASS (class);
216
parent_class = g_type_class_peek_parent (class);
218
mg_qf_all_signals[TEMPL_SIGNAL] =
219
g_signal_new ("templ_signal",
220
G_TYPE_FROM_CLASS (object_class),
222
G_STRUCT_OFFSET (MgQfAllClass, templ_signal),
224
marshal_VOID__VOID, G_TYPE_NONE,
226
class->templ_signal = NULL;
228
object_class->dispose = mg_qf_all_dispose;
229
object_class->finalize = mg_qf_all_finalize;
232
object_class->set_property = mg_qf_all_set_property;
233
object_class->get_property = mg_qf_all_get_property;
234
g_object_class_install_property (object_class, PROP_QUERY,
235
g_param_spec_pointer ("query", NULL, NULL,
236
(G_PARAM_READABLE | G_PARAM_WRITABLE)));
238
/* virtual functions */
240
MG_BASE_CLASS (class)->dump = (void (*)(MgBase *, guint)) mg_qf_all_dump;
242
MG_QFIELD_CLASS (class)->copy = mg_qf_all_copy;
243
MG_QFIELD_CLASS (class)->is_equal = mg_qf_all_is_equal;
244
MG_QFIELD_CLASS (class)->is_list = NULL;
245
MG_QFIELD_CLASS (class)->get_params = NULL;
249
mg_qf_all_init (MgQfAll *mg_qf_all)
251
mg_qf_all->priv = g_new0 (MgQfAllPrivate, 1);
252
mg_qf_all->priv->query = NULL;
253
mg_qf_all->priv->target_ref = NULL;
258
* mg_qf_all_new_with_target
259
* @query: a #MgQuery in which the new object will be
260
* @target: a #MgTarget object
262
* Creates a new MgQfAll object which represents all the fields of the entity represented
263
* by @target. For example if @target represents my_table, then the created object would
264
* represent 'my_table.*' in SQL notation
266
* Returns: the new object
269
mg_qf_all_new_with_target (MgQuery *query, MgTarget *target)
276
g_return_val_if_fail (query && IS_MG_QUERY (query), NULL);
277
g_return_val_if_fail (target && IS_MG_TARGET (target), NULL);
278
g_return_val_if_fail (mg_target_get_query (target) == query, NULL);
279
conf = mg_base_get_conf (MG_BASE (query));
281
obj = g_object_new (MG_QF_ALL_TYPE, "conf", conf, NULL);
282
mg_qf_all = MG_QF_ALL (obj);
283
g_object_get (G_OBJECT (query), "field_serial", &id, NULL);
284
mg_base_set_id (MG_BASE (mg_qf_all), id);
286
mg_qf_all->priv->query = query;
287
g_signal_connect (G_OBJECT (query), "nullified",
288
G_CALLBACK (nullified_object_cb), mg_qf_all);
290
mg_qf_all->priv->target_ref = MG_REF_BASE (mg_ref_base_new (conf));
291
mg_ref_base_set_ref_object (mg_qf_all->priv->target_ref, MG_BASE (target));
297
* mg_qf_all_new_with_xml_id
298
* @query: a #MgQuery in which the new object will be
299
* @target_xml_id: the XML Id of a #MgTarget object
301
* Creates a new MgQfAll object which represents all the fields of the entity represented
302
* by the target identified by @target_xml_id.
304
* Returns: the new object
307
mg_qf_all_new_with_xml_id (MgQuery *query, const gchar *target_xml_id)
312
gchar *str, *ptr, *tok, *qid;
315
g_return_val_if_fail (query && IS_MG_QUERY (query), NULL);
316
g_return_val_if_fail (target_xml_id && *target_xml_id, NULL);
317
qid = mg_xml_storage_get_xml_id (MG_XML_STORAGE (query));
318
str = g_strdup (target_xml_id);
319
ptr = strtok_r (str, ":", &tok);
320
g_return_val_if_fail (!strcmp (ptr, qid), NULL);
324
conf = mg_base_get_conf (MG_BASE (query));
325
obj = g_object_new (MG_QF_ALL_TYPE, "conf", conf, NULL);
326
mg_qf_all = MG_QF_ALL (obj);
327
g_object_get (G_OBJECT (query), "field_serial", &id, NULL);
328
mg_base_set_id (MG_BASE (mg_qf_all), id);
330
mg_qf_all->priv->query = query;
331
g_signal_connect (G_OBJECT (query), "nullified",
332
G_CALLBACK (nullified_object_cb), mg_qf_all);
334
mg_qf_all->priv->target_ref = MG_REF_BASE (mg_ref_base_new (conf));
335
mg_ref_base_set_ref_name (mg_qf_all->priv->target_ref, MG_TARGET_TYPE, REFERENCE_BY_XML_ID, target_xml_id);
341
nullified_object_cb (GObject *obj, MgQfAll *field)
343
mg_base_nullify (MG_BASE (field));
347
mg_qf_all_dispose (GObject *object)
351
g_return_if_fail (object != NULL);
352
g_return_if_fail (IS_MG_QF_ALL (object));
354
mg_qf_all = MG_QF_ALL (object);
355
if (mg_qf_all->priv) {
356
mg_base_nullify_check (MG_BASE (object));
358
if (mg_qf_all->priv->query) {
359
g_signal_handlers_disconnect_by_func (G_OBJECT (mg_qf_all->priv->query),
360
G_CALLBACK (nullified_object_cb), mg_qf_all);
361
mg_qf_all->priv->query = NULL;
363
if (mg_qf_all->priv->target_ref) {
364
g_object_unref (G_OBJECT (mg_qf_all->priv->target_ref));
365
mg_qf_all->priv->target_ref = NULL;
370
parent_class->dispose (object);
374
mg_qf_all_finalize (GObject * object)
378
g_return_if_fail (object != NULL);
379
g_return_if_fail (IS_MG_QF_ALL (object));
381
mg_qf_all = MG_QF_ALL (object);
382
if (mg_qf_all->priv) {
383
g_free (mg_qf_all->priv);
384
mg_qf_all->priv = NULL;
388
parent_class->finalize (object);
393
mg_qf_all_set_property (GObject *object,
401
mg_qf_all = MG_QF_ALL (object);
402
if (mg_qf_all->priv) {
405
ptr = g_value_get_pointer (value);
406
g_return_if_fail (ptr && IS_MG_QUERY (ptr));
408
if (mg_qf_all->priv->query) {
409
if (mg_qf_all->priv->query == MG_QUERY (ptr))
412
g_signal_handlers_disconnect_by_func (G_OBJECT (mg_qf_all->priv->query),
413
G_CALLBACK (nullified_object_cb), mg_qf_all);
416
mg_qf_all->priv->query = MG_QUERY (ptr);
417
g_signal_connect (G_OBJECT (ptr), "nullified",
418
G_CALLBACK (nullified_object_cb), mg_qf_all);
425
mg_qf_all_get_property (GObject *object,
431
mg_qf_all = MG_QF_ALL (object);
433
if (mg_qf_all->priv) {
436
g_value_set_pointer (value, mg_qf_all->priv->query);
443
mg_qf_all_copy (MgQfield *orig)
447
g_assert (IS_MG_QF_ALL (orig));
448
qf = MG_QF_ALL (orig);
450
obj = mg_qf_all_new_with_xml_id (qf->priv->query,
451
mg_ref_base_get_ref_name (qf->priv->target_ref, NULL, NULL));
452
if (mg_base_get_name (MG_BASE (orig)))
453
mg_base_set_name (MG_BASE (obj), mg_base_get_name (MG_BASE (orig)));
455
if (mg_base_get_description (MG_BASE (orig)))
456
mg_base_set_description (MG_BASE (obj), mg_base_get_description (MG_BASE (orig)));
462
mg_qf_all_is_equal (MgQfield *qfield1, MgQfield *qfield2)
464
const gchar *ref1, *ref2;
465
g_assert (IS_MG_QF_ALL (qfield1));
466
g_assert (IS_MG_QF_ALL (qfield2));
468
/* it is here assumed that qfield1 and qfield2 are of the same type and refer to the same
470
ref1 = mg_ref_base_get_ref_name (MG_QF_ALL (qfield1)->priv->target_ref, NULL, NULL);
471
ref2 = mg_ref_base_get_ref_name (MG_QF_ALL (qfield2)->priv->target_ref, NULL, NULL);
473
return !strcmp (ref1, ref2) ? TRUE : FALSE;
477
* mg_qf_all_get_target
478
* @field: a #MgQfAll object
480
* Get the #MgTarget object @field 'belongs' to
482
* Returns: the #MgTarget object
485
mg_qf_all_get_target (MgQfAll *field)
488
g_return_val_if_fail (field && IS_MG_QF_ALL (field), NULL);
489
g_return_val_if_fail (field->priv, NULL);
491
base = mg_ref_base_get_ref_object (field->priv->target_ref);
493
return MG_TARGET (base);
500
mg_qf_all_dump (MgQfAll *field, guint offset)
505
g_return_if_fail (field && IS_MG_QF_ALL (field));
507
/* string for the offset */
508
str = g_new0 (gchar, offset+1);
509
for (i=0; i<offset; i++)
515
g_print ("%s" D_COL_H1 "MgQfAll" D_COL_NOR " \"%s\" (%p, id=%d) ",
516
str, mg_base_get_name (MG_BASE (field)), field, mg_base_get_id (MG_BASE (field)));
517
if (mg_qf_all_is_active (MG_REFERER (field)))
518
g_print ("Active, ");
520
g_print (D_COL_ERR "Inactive" D_COL_NOR ", ");
521
g_print ("references %p (%s)\n",
522
mg_ref_base_get_ref_object (field->priv->target_ref),
523
mg_ref_base_get_ref_name (field->priv->target_ref, NULL, NULL));
526
g_print ("%s" D_COL_ERR "Using finalized object %p" D_COL_NOR, str, field);
532
* MgField interface implementation
535
mg_qf_all_get_entity (MgField *iface)
537
g_return_val_if_fail (iface && IS_MG_QF_ALL (iface), NULL);
538
g_return_val_if_fail (MG_QF_ALL (iface)->priv, NULL);
540
return MG_ENTITY (MG_QF_ALL (iface)->priv->query);
543
static MgServerDataType *
544
mg_qf_all_get_data_type (MgField *iface)
546
g_return_val_if_fail (iface && IS_MG_QF_ALL (iface), NULL);
547
g_return_val_if_fail (MG_QF_ALL (iface)->priv, NULL);
553
* MgXmlStorage interface implementation
556
mg_qf_all_get_xml_id (MgXmlStorage *iface)
558
gchar *q_xml_id, *xml_id;
560
g_return_val_if_fail (iface && IS_MG_QF_ALL (iface), NULL);
561
g_return_val_if_fail (MG_QF_ALL (iface)->priv, NULL);
563
q_xml_id = mg_xml_storage_get_xml_id (MG_XML_STORAGE (MG_QF_ALL (iface)->priv->query));
564
xml_id = g_strdup_printf ("%s:QF%d", q_xml_id, mg_base_get_id (MG_BASE (iface)));
571
mg_qf_all_save_to_xml (MgXmlStorage *iface, GError **error)
573
xmlNodePtr node = NULL;
577
g_return_val_if_fail (iface && IS_MG_QF_ALL (iface), NULL);
578
g_return_val_if_fail (MG_QF_ALL (iface)->priv, NULL);
580
field = MG_QF_ALL (iface);
582
node = xmlNewNode (NULL, "MG_QF");
584
str = mg_qf_all_get_xml_id (iface);
585
xmlSetProp (node, "id", str);
588
xmlSetProp (node, "type", "ALL");
589
xmlSetProp (node, "name", mg_base_get_name (MG_BASE (field)));
590
xmlSetProp (node, "target", mg_ref_base_get_ref_name (field->priv->target_ref, NULL, NULL));
591
if (! mg_qfield_is_visible (MG_QFIELD (field)))
592
xmlSetProp (node, "is_visible", "f");
593
if (mg_qfield_is_internal (MG_QFIELD (field)))
594
xmlSetProp (node, "is_internal", "t");
600
mg_qf_all_load_from_xml (MgXmlStorage *iface, xmlNodePtr node, GError **error)
604
gboolean target = FALSE;
606
g_return_val_if_fail (iface && IS_MG_QF_ALL (iface), FALSE);
607
g_return_val_if_fail (MG_QF_ALL (iface)->priv, FALSE);
608
g_return_val_if_fail (node, FALSE);
610
field = MG_QF_ALL (iface);
611
if (strcmp (node->name, "MG_QF")) {
614
MG_QF_ALL_XML_LOAD_ERROR,
615
_("XML Tag is not <MG_QF>"));
619
prop = xmlGetProp (node, "type");
621
if (strcmp (prop, "ALL")) {
624
MG_QF_ALL_XML_LOAD_ERROR,
625
_("Wrong type of field in <MG_QF>"));
631
prop = xmlGetProp (node, "id");
634
ptr = strtok_r (prop, ":", &tok);
635
ptr = strtok_r (NULL, ":", &tok);
636
if (strlen (ptr) < 3) {
639
MG_QF_ALL_XML_LOAD_ERROR,
640
_("Wrong 'id' attribute in <MG_QF>"));
643
mg_base_set_id (MG_BASE (field), atoi (ptr+2));
647
prop = xmlGetProp (node, "name");
649
mg_base_set_name (MG_BASE (field), prop);
653
prop = xmlGetProp (node, "target");
656
mg_ref_base_set_ref_name (field->priv->target_ref, MG_TARGET_TYPE, REFERENCE_BY_XML_ID, prop);
660
prop = xmlGetProp (node, "is_visible");
662
mg_qfield_set_visible (MG_QFIELD (field), (*prop == 't') ? TRUE : FALSE);
666
prop = xmlGetProp (node, "is_internal");
668
mg_qfield_set_internal (MG_QFIELD (field), (*prop == 't') ? TRUE : FALSE);
677
MG_QF_ALL_XML_LOAD_ERROR,
678
_("Missing required attributes for <MG_QF>"));
685
* MgRenderer interface implementation
688
mg_qf_all_render_as_xql (MgRenderer *iface, MgContext *context, GError **error)
690
GdaXqlItem *node = NULL;
692
g_return_val_if_fail (iface && IS_MG_QF_ALL (iface), NULL);
693
g_return_val_if_fail (MG_QF_ALL (iface)->priv, NULL);
700
mg_qf_all_render_as_sql (MgRenderer *iface, MgContext *context, guint options, GError **error)
706
g_return_val_if_fail (iface && IS_MG_QF_ALL (iface), NULL);
707
g_return_val_if_fail (MG_QF_ALL (iface)->priv, NULL);
708
field = MG_QF_ALL (iface);
710
base = mg_ref_base_get_ref_object (field->priv->target_ref);
712
str = g_strdup_printf ("%s.*", mg_target_get_alias (MG_TARGET (base)));
716
MG_QF_ALL_RENDER_ERROR,
717
_("Can't find target '%s'"), mg_ref_base_get_ref_name (field->priv->target_ref,
724
mg_qf_all_render_as_str (MgRenderer *iface, MgContext *context)
730
g_return_val_if_fail (iface && IS_MG_QF_ALL (iface), NULL);
731
g_return_val_if_fail (MG_QF_ALL (iface)->priv, NULL);
732
field = MG_QF_ALL (iface);
734
base = mg_ref_base_get_ref_object (field->priv->target_ref);
736
MgEntity *ent = mg_target_get_represented_entity (MG_TARGET (base));
737
str = g_strdup_printf ("%s(%s).*", mg_base_get_name (MG_BASE (ent)),
738
mg_target_get_alias (MG_TARGET (base)));
741
str = g_strdup (_("Non activated field"));
747
* MgReferer interface implementation
750
mg_qf_all_activate (MgReferer *iface)
752
g_return_val_if_fail (iface && IS_MG_QF_ALL (iface), FALSE);
753
g_return_val_if_fail (MG_QF_ALL (iface)->priv, FALSE);
755
return mg_ref_base_activate (MG_QF_ALL (iface)->priv->target_ref);
759
mg_qf_all_deactivate (MgReferer *iface)
761
g_return_if_fail (iface && IS_MG_QF_ALL (iface));
762
g_return_if_fail (MG_QF_ALL (iface)->priv);
764
mg_ref_base_deactivate (MG_QF_ALL (iface)->priv->target_ref);
768
mg_qf_all_is_active (MgReferer *iface)
770
g_return_val_if_fail (iface && IS_MG_QF_ALL (iface), FALSE);
771
g_return_val_if_fail (MG_QF_ALL (iface)->priv, FALSE);
773
return mg_ref_base_is_active (MG_QF_ALL (iface)->priv->target_ref);
777
mg_qf_all_get_ref_objects (MgReferer *iface)
782
g_return_val_if_fail (iface && IS_MG_QF_ALL (iface), NULL);
783
g_return_val_if_fail (MG_QF_ALL (iface)->priv, NULL);
785
base = mg_ref_base_get_ref_object (MG_QF_ALL (iface)->priv->target_ref);
787
list = g_slist_append (list, base);
793
mg_qf_all_replace_refs (MgReferer *iface, GHashTable *replacements)
797
g_return_if_fail (iface && IS_MG_QF_ALL (iface));
798
g_return_if_fail (MG_QF_ALL (iface)->priv);
800
field = MG_QF_ALL (iface);
801
if (field->priv->query) {
802
MgQuery *query = g_hash_table_lookup (replacements, field->priv->query);
804
g_signal_handlers_disconnect_by_func (G_OBJECT (field->priv->query),
805
G_CALLBACK (nullified_object_cb), field);
806
field->priv->query = query;
807
g_signal_connect (G_OBJECT (query), "nullified",
808
G_CALLBACK (nullified_object_cb), field);
812
mg_ref_base_replace_ref_object (field->priv->target_ref, replacements);