~ubuntu-branches/ubuntu/oneiric/libgdata/oneiric-backports

« back to all changes in this revision

Viewing changes to gdata/gd/gdata-gd-feed-link.c

  • Committer: Package Import Robot
  • Author(s): Evan Broder
  • Date: 2011-11-15 21:59:48 UTC
  • mfrom: (4.1.4 experimental)
  • Revision ID: package-import@ubuntu.com-20111115215948-e17s889ocgu5fv4f
Tags: 0.10.1-1~oneiric1
Automated backport upload; no source changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
 
2
/*
 
3
 * GData Client
 
4
 * Copyright (C) Philip Withnall 2010 <philip@tecnocode.co.uk>
 
5
 * Copyright (C) Richard Schwarting 2010 <aquarichy@gmail.com>
 
6
 *
 
7
 * GData Client is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * GData Client is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with GData Client.  If not, see <http://www.gnu.org/licenses/>.
 
19
 */
 
20
 
 
21
/*
 
22
 * SECTION:gdata-gd-feed-link
 
23
 * @short_description: GD feed link element
 
24
 * @stability: Unstable
 
25
 * @include: gdata/gd/gdata-gd-feed-link.h
 
26
 *
 
27
 * #GDataGDFeedLink represents a "feedLink" element from the
 
28
 * <ulink type="http" url="http://code.google.com/apis/gdata/docs/2.0/elements.html#gdFeedLink">GData specification</ulink>.
 
29
 *
 
30
 * It is private API, since implementing classes are likely to proxy the properties and functions
 
31
 * of #GDataGDFeedLink as appropriate; most entry types which implement #GDataGDFeedLink have no use
 
32
 * for most of its properties, and it would be unnecessary and confusing to expose #GDataGDFeedLink itself.
 
33
 *
 
34
 * In its current state, #GDataGDFeedLink supports the <code class="literal">href</code> attribute, but doesn't support inline
 
35
 * <code class="literal">feed</code> elements, since they don't seem to appear in the wild.
 
36
 *
 
37
 * Since: 0.10.0
 
38
 */
 
39
 
 
40
#include <glib.h>
 
41
#include <libxml/parser.h>
 
42
#include <string.h>
 
43
 
 
44
#include "gdata-gd-feed-link.h"
 
45
#include "gdata-parsable.h"
 
46
#include "gdata-parser.h"
 
47
#include "gdata-private.h"
 
48
 
 
49
static void gdata_gd_feed_link_finalize (GObject *object);
 
50
static void gdata_gd_feed_link_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
 
51
static void gdata_gd_feed_link_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec);
 
52
static gboolean pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointer user_data, GError **error);
 
53
static void pre_get_xml (GDataParsable *parsable, GString *xml_string);
 
54
static void get_namespaces (GDataParsable *parsable, GHashTable *namespaces);
 
55
 
 
56
struct _GDataGDFeedLinkPrivate {
 
57
        gchar *uri;
 
58
        gchar *relation_type;
 
59
        gint count_hint;
 
60
        gboolean is_read_only;
 
61
};
 
62
 
 
63
enum {
 
64
        PROP_RELATION_TYPE = 1,
 
65
        PROP_URI,
 
66
        PROP_COUNT_HINT,
 
67
        PROP_IS_READ_ONLY,
 
68
};
 
69
 
 
70
G_DEFINE_TYPE (GDataGDFeedLink, gdata_gd_feed_link, GDATA_TYPE_PARSABLE)
 
71
 
 
72
static void
 
73
gdata_gd_feed_link_class_init (GDataGDFeedLinkClass *klass)
 
74
{
 
75
        GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
76
        GDataParsableClass *parsable_class = GDATA_PARSABLE_CLASS (klass);
 
77
 
 
78
        g_type_class_add_private (klass, sizeof (GDataGDFeedLinkPrivate));
 
79
 
 
80
        gobject_class->set_property = gdata_gd_feed_link_set_property;
 
81
        gobject_class->get_property = gdata_gd_feed_link_get_property;
 
82
        gobject_class->finalize = gdata_gd_feed_link_finalize;
 
83
 
 
84
        parsable_class->pre_parse_xml = pre_parse_xml;
 
85
        parsable_class->pre_get_xml = pre_get_xml;
 
86
        parsable_class->get_namespaces = get_namespaces;
 
87
        parsable_class->element_name = "feedLink";
 
88
        parsable_class->element_namespace = "gd";
 
89
 
 
90
        /**
 
91
         * GDataGDFeedLink:relation-type:
 
92
         *
 
93
         * Describes the relation type of the given feed to its parent feed.
 
94
         *
 
95
         * For more information, see the
 
96
         * <ulink type="http" url="http://code.google.com/apis/gdata/docs/2.0/elements.html#gdFeedLink">GData specification</ulink>.
 
97
         *
 
98
         * Since: 0.10.0
 
99
         */
 
100
        g_object_class_install_property (gobject_class, PROP_RELATION_TYPE,
 
101
                                         g_param_spec_string ("relation-type",
 
102
                                                              "Relation type", "Describes the relation type of the given feed to its parent feed.",
 
103
                                                              GDATA_LINK_ALTERNATE,
 
104
                                                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
105
 
 
106
        /**
 
107
         * GDataGDFeedLink:uri:
 
108
         *
 
109
         * A URI describing the location of the designated feed.
 
110
         *
 
111
         * For more information, see the
 
112
         * <ulink type="http" url="http://code.google.com/apis/gdata/docs/2.0/elements.html#gdFeedLink">GData specification</ulink>.
 
113
         *
 
114
         * Since: 0.10.0
 
115
         */
 
116
        g_object_class_install_property (gobject_class, PROP_URI,
 
117
                                         g_param_spec_string ("uri",
 
118
                                                              "URI", "A URI describing the location of the designated feed.",
 
119
                                                              NULL,
 
120
                                                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
121
 
 
122
        /**
 
123
         * GDataGDFeedLink:count-hint:
 
124
         *
 
125
         * Hints at the number of entries contained in the designated feed, and may not be reliable.
 
126
         *
 
127
         * For more information, see the
 
128
         * <ulink type="http" url="http://code.google.com/apis/gdata/docs/2.0/elements.html#gdFeedLink">GData specification</ulink>.
 
129
         *
 
130
         * Since: 0.10.0
 
131
         */
 
132
        g_object_class_install_property (gobject_class, PROP_COUNT_HINT,
 
133
                                         g_param_spec_int ("count-hint",
 
134
                                                           "Count hint", "Hints at the number of entries contained in the designated feed.",
 
135
                                                           -1, G_MAXINT, -1,
 
136
                                                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
137
 
 
138
        /**
 
139
         * GDataGDFeedLink:is-read-only:
 
140
         *
 
141
         * Indicates whether the feed is read only.
 
142
         *
 
143
         * For more information, see the
 
144
         * <ulink type="http" url="http://code.google.com/apis/gdata/docs/2.0/elements.html#gdFeedLink">GData specification</ulink>.
 
145
         *
 
146
         * Since: 0.10.0
 
147
         */
 
148
        g_object_class_install_property (gobject_class, PROP_IS_READ_ONLY,
 
149
                                         g_param_spec_boolean ("is-read-only",
 
150
                                                               "Read only?", "Indicates whether the feed is read only.",
 
151
                                                               TRUE,
 
152
                                                               G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
 
153
}
 
154
 
 
155
static void
 
156
gdata_gd_feed_link_init (GDataGDFeedLink *self)
 
157
{
 
158
        self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_GD_FEED_LINK, GDataGDFeedLinkPrivate);
 
159
        self->priv->count_hint = -1;
 
160
        self->priv->relation_type = g_strdup (GDATA_LINK_ALTERNATE);
 
161
}
 
162
 
 
163
static void
 
164
gdata_gd_feed_link_finalize (GObject *object)
 
165
{
 
166
        GDataGDFeedLinkPrivate *priv = GDATA_GD_FEED_LINK (object)->priv;
 
167
 
 
168
        g_free (priv->uri);
 
169
        g_free (priv->relation_type);
 
170
 
 
171
        /* Chain up to the parent class */
 
172
        G_OBJECT_CLASS (gdata_gd_feed_link_parent_class)->finalize (object);
 
173
}
 
174
 
 
175
static void
 
176
gdata_gd_feed_link_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
 
177
{
 
178
        GDataGDFeedLinkPrivate *priv = GDATA_GD_FEED_LINK (object)->priv;
 
179
 
 
180
        switch (property_id) {
 
181
                case PROP_RELATION_TYPE:
 
182
                        g_value_set_string (value, priv->relation_type);
 
183
                        break;
 
184
                case PROP_URI:
 
185
                        g_value_set_string (value, priv->uri);
 
186
                        break;
 
187
                case PROP_COUNT_HINT:
 
188
                        g_value_set_int (value, priv->count_hint);
 
189
                        break;
 
190
                case PROP_IS_READ_ONLY:
 
191
                        g_value_set_boolean (value, priv->is_read_only);
 
192
                        break;
 
193
                default:
 
194
                        /* We don't have any other properties... */
 
195
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
196
                        break;
 
197
        }
 
198
}
 
199
 
 
200
static void
 
201
gdata_gd_feed_link_set_property (GObject *object, guint property_id, const GValue *value, GParamSpec *pspec)
 
202
{
 
203
        GDataGDFeedLink *self = GDATA_GD_FEED_LINK (object);
 
204
 
 
205
        switch (property_id) {
 
206
                case PROP_RELATION_TYPE:
 
207
                        gdata_gd_feed_link_set_relation_type (self, g_value_get_string (value));
 
208
                        break;
 
209
                case PROP_URI:
 
210
                        gdata_gd_feed_link_set_uri (self, g_value_get_string (value));
 
211
                        break;
 
212
                case PROP_COUNT_HINT:
 
213
                        gdata_gd_feed_link_set_count_hint (self, g_value_get_int (value));
 
214
                        break;
 
215
                case PROP_IS_READ_ONLY:
 
216
                        gdata_gd_feed_link_set_is_read_only (self, g_value_get_boolean (value));
 
217
                        break;
 
218
                default:
 
219
                        /* We don't have any other properties... */
 
220
                        G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
 
221
                        break;
 
222
        }
 
223
}
 
224
 
 
225
static gboolean
 
226
pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointer user_data, GError **error)
 
227
{
 
228
        xmlChar *rel, *href, *count_hint;
 
229
        GDataGDFeedLink *self = GDATA_GD_FEED_LINK (parsable);
 
230
 
 
231
        rel = xmlGetProp (root_node, (xmlChar*) "rel");
 
232
        if (rel != NULL && *rel == '\0') {
 
233
                xmlFree (rel);
 
234
                return gdata_parser_error_required_property_missing (root_node, "rel", error);
 
235
        }
 
236
 
 
237
        gdata_gd_feed_link_set_relation_type (self, (const gchar*) rel);
 
238
        xmlFree (rel);
 
239
 
 
240
        href = xmlGetProp (root_node, (xmlChar*) "href");
 
241
        if (href == NULL || *href == '\0') {
 
242
                xmlFree (href);
 
243
                return gdata_parser_error_required_property_missing (root_node, "href", error);
 
244
        }
 
245
        self->priv->uri = (gchar*) href;
 
246
 
 
247
        count_hint = xmlGetProp (root_node, (xmlChar*) "countHint");
 
248
        self->priv->count_hint = (count_hint != NULL) ? strtol ((char*) count_hint, NULL, 10) : -1;
 
249
        xmlFree (count_hint);
 
250
 
 
251
        return gdata_parser_boolean_from_property (root_node, "readOnly", &(self->priv->is_read_only), 0, error);
 
252
}
 
253
 
 
254
static void
 
255
pre_get_xml (GDataParsable *parsable, GString *xml_string)
 
256
{
 
257
        GDataGDFeedLinkPrivate *priv = GDATA_GD_FEED_LINK (parsable)->priv;
 
258
 
 
259
        if (priv->relation_type != NULL) {
 
260
                gdata_parser_string_append_escaped (xml_string, " rel='", priv->relation_type, "'");
 
261
        }
 
262
 
 
263
        if (priv->uri != NULL) {
 
264
                gdata_parser_string_append_escaped (xml_string, " href='", priv->uri, "'");
 
265
        }
 
266
 
 
267
        if (priv->count_hint != -1) {
 
268
                g_string_append_printf (xml_string, " countHint='%i'", priv->count_hint);
 
269
        }
 
270
 
 
271
        if (priv->is_read_only == TRUE) {
 
272
                g_string_append_printf (xml_string, " readOnly='true'");
 
273
        } else {
 
274
                g_string_append_printf (xml_string, " readOnly='false'");
 
275
        }
 
276
}
 
277
 
 
278
static void
 
279
get_namespaces (GDataParsable *parsable, GHashTable *namespaces)
 
280
{
 
281
        g_hash_table_insert (namespaces, (gchar*) "gd", (gchar*) "http://schemas.google.com/g/2005");
 
282
}
 
283
 
 
284
/**
 
285
 * gdata_gd_feed_link_get_relation_type:
 
286
 * @self: a #GDataGDFeedLink
 
287
 *
 
288
 * Gets the #GDataGDFeedLink:relation-type property.
 
289
 *
 
290
 * Return value: the feed's relation to its owner, or %NULL
 
291
 *
 
292
 * Since: 0.10.0
 
293
 */
 
294
const gchar *
 
295
gdata_gd_feed_link_get_relation_type (GDataGDFeedLink *self)
 
296
{
 
297
        g_return_val_if_fail (GDATA_IS_GD_FEED_LINK (self), NULL);
 
298
 
 
299
        return self->priv->relation_type;
 
300
}
 
301
 
 
302
/**
 
303
 * gdata_gd_feed_link_get_uri:
 
304
 * @self: a #GDataGDFeedLink
 
305
 *
 
306
 * Gets the #GDataGDFeedLink:uri property.
 
307
 *
 
308
 * Return value: the related feed's URI
 
309
 *
 
310
 * Since: 0.10.0
 
311
 */
 
312
const gchar *
 
313
gdata_gd_feed_link_get_uri (GDataGDFeedLink *self)
 
314
{
 
315
        g_return_val_if_fail (GDATA_IS_GD_FEED_LINK (self), NULL);
 
316
 
 
317
        return self->priv->uri;
 
318
}
 
319
 
 
320
/**
 
321
 * gdata_gd_feed_link_get_count_hint:
 
322
 * @self: a #GDataGDFeedLink
 
323
 *
 
324
 * Gets the #GDataGDFeedLink:count-hint property.
 
325
 *
 
326
 * Return value: the potential number of entries in the related feed, or <code class="literal">-1</code> if not set
 
327
 *
 
328
 * Since: 0.10.0
 
329
 */
 
330
gint
 
331
gdata_gd_feed_link_get_count_hint (GDataGDFeedLink *self)
 
332
{
 
333
        g_return_val_if_fail (GDATA_IS_GD_FEED_LINK (self), -1);
 
334
 
 
335
        return self->priv->count_hint;
 
336
}
 
337
 
 
338
/**
 
339
 * gdata_gd_feed_link_get_read_only:
 
340
 * @self: a #GDataGDFeedLink
 
341
 *
 
342
 * Gets the #GDataGDFeedLink:read-only property.
 
343
 *
 
344
 * Return value: %TRUE if the feed is read only, %FALSE otherwise
 
345
 *
 
346
 * Since: 0.10.0
 
347
 */
 
348
gboolean
 
349
gdata_gd_feed_link_is_read_only (GDataGDFeedLink *self)
 
350
{
 
351
        g_return_val_if_fail (GDATA_IS_GD_FEED_LINK (self), FALSE);
 
352
 
 
353
        return self->priv->is_read_only;
 
354
}
 
355
 
 
356
/**
 
357
 * gdata_gd_feed_link_set_relation_type:
 
358
 * @self: a #GDataGDFeedLink
 
359
 * @relation_type: (allow-none): the new relation type between the feed and its owner, or %NULL
 
360
 *
 
361
 * Sets the relation type of the #GDataGDFeedLink's related feed to @relation_type. If @relation_type is one of the standard Atom relation types,
 
362
 * use one of the defined relation type values, instead of a static string. e.g. %GDATA_LINK_EDIT or %GDATA_LINK_SELF.
 
363
 *
 
364
 * Since: 0.10.0
 
365
 */
 
366
void
 
367
gdata_gd_feed_link_set_relation_type (GDataGDFeedLink *self, const gchar *relation_type)
 
368
{
 
369
        g_return_if_fail (GDATA_IS_GD_FEED_LINK (self));
 
370
        g_return_if_fail (relation_type == NULL || *relation_type != '\0');
 
371
 
 
372
        /* If the relation type is unset, use the default "alternate" relation type. If it's set, and isn't an IRI, turn it into an IRI
 
373
         * by appending it to "http://www.iana.org/assignments/relation/". If it's set and is an IRI, just use the IRI.
 
374
         * See: http://www.atomenabled.org/developers/syndication/atom-format-spec.php#rel_attribute
 
375
         */
 
376
        g_free (self->priv->relation_type);
 
377
        if (relation_type == NULL) {
 
378
                self->priv->relation_type = g_strdup (GDATA_LINK_ALTERNATE);
 
379
        } else if (strchr ((char*) relation_type, ':') == NULL) {
 
380
                self->priv->relation_type = g_strconcat ("http://www.iana.org/assignments/relation/", (const gchar*) relation_type, NULL);
 
381
        } else {
 
382
                self->priv->relation_type = g_strdup ((gchar*) relation_type);
 
383
        }
 
384
 
 
385
        g_object_notify (G_OBJECT (self), "relation-type");
 
386
}
 
387
 
 
388
/**
 
389
 * gdata_gd_feed_link_set_uri:
 
390
 * @self: a #GDataGDFeedLink
 
391
 * @uri: the new URI for the related feed
 
392
 *
 
393
 * Sets the URI of the #GDataGDFeedLink's related feed to @uri.
 
394
 *
 
395
 * Since: 0.10.0
 
396
 */
 
397
void
 
398
gdata_gd_feed_link_set_uri (GDataGDFeedLink *self, const gchar *uri)
 
399
{
 
400
        g_return_if_fail (GDATA_IS_GD_FEED_LINK (self));
 
401
        g_return_if_fail (uri != NULL && *uri != '\0');
 
402
 
 
403
        g_free (self->priv->uri);
 
404
        self->priv->uri = g_strdup (uri);
 
405
 
 
406
        g_object_notify (G_OBJECT (self), "uri");
 
407
}
 
408
 
 
409
/**
 
410
 * gdata_gd_feed_link_set_count_hint:
 
411
 * @self: a #GDataGDFeedLink
 
412
 * @count_hint: the new number of entries in the related feed, or <code class="literal">-1</code> if unknown
 
413
 *
 
414
 * Sets the number of entries in the #GDataGDFeedLink's related feed to @count_hint. This number may be an imprecise estimate.
 
415
 *
 
416
 * Since: 0.10.0
 
417
 */
 
418
void
 
419
gdata_gd_feed_link_set_count_hint (GDataGDFeedLink *self, gint count_hint)
 
420
{
 
421
        g_return_if_fail (GDATA_IS_GD_FEED_LINK (self));
 
422
        g_return_if_fail (count_hint >= -1);
 
423
 
 
424
        self->priv->count_hint = count_hint;
 
425
 
 
426
        g_object_notify (G_OBJECT (self), "count-hint");
 
427
}
 
428
 
 
429
/**
 
430
 * gdata_gd_feed_link_set_is_read_only:
 
431
 * @self: a #GDataGDFeedLink
 
432
 * @is_read_only: %TRUE if the #GDataGDFeedLink's related feed is read only, %FALSE otherwise
 
433
 *
 
434
 * Sets the read only status of the #GDataGDFeedLink's related feed to @is_read_only.
 
435
 *
 
436
 * Since: 0.10.0
 
437
 */
 
438
void
 
439
gdata_gd_feed_link_set_is_read_only (GDataGDFeedLink *self, gboolean is_read_only)
 
440
{
 
441
        g_return_if_fail (GDATA_IS_GD_FEED_LINK (self));
 
442
 
 
443
        self->priv->is_read_only = is_read_only;
 
444
 
 
445
        g_object_notify (G_OBJECT (self), "is-read-only");
 
446
}
 
447