1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * GData Client
4 * Copyright (C) Philip Withnall 2009–2010 <philip@tecnocode.co.uk>
5 *
6 * GData Client is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * GData Client is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with GData Client. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 /**
21 * SECTION:gdata-generator
22 * @short_description: Atom generator element
23 * @stability: Stable
24 * @include: gdata/atom/gdata-generator.h
25 *
26 * #GDataGenerator represents a "generator" element from the
27 * <ulink type="http" url="http://www.atomenabled.org/developers/syndication/atom-format-spec.php">Atom specification</ulink>.
28 */
29
30 #include <glib.h>
31 #include <libxml/parser.h>
32
33 #include "gdata-generator.h"
34 #include "gdata-parsable.h"
35 #include "gdata-parser.h"
36 #include "gdata-comparable.h"
37
38 static void gdata_generator_comparable_init (GDataComparableIface *iface);
39 static void gdata_generator_finalize (GObject *object);
40 static void gdata_generator_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec);
41 static gboolean pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointer user_data, GError **error);
42 static gboolean parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointer user_data, GError **error);
43
44 struct _GDataGeneratorPrivate {
45 gchar *name;
46 gchar *uri;
47 gchar *version;
48 };
49
50 enum {
51 PROP_NAME = 1,
52 PROP_URI,
53 PROP_VERSION
54 };
55
G_DEFINE_TYPE_WITH_CODE(GDataGenerator,gdata_generator,GDATA_TYPE_PARSABLE,G_IMPLEMENT_INTERFACE (GDATA_TYPE_COMPARABLE,gdata_generator_comparable_init))56 G_DEFINE_TYPE_WITH_CODE (GDataGenerator, gdata_generator, GDATA_TYPE_PARSABLE,
57 G_IMPLEMENT_INTERFACE (GDATA_TYPE_COMPARABLE, gdata_generator_comparable_init))
58
59 static void
60 gdata_generator_class_init (GDataGeneratorClass *klass)
61 {
62 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
63 GDataParsableClass *parsable_class = GDATA_PARSABLE_CLASS (klass);
64
65 g_type_class_add_private (klass, sizeof (GDataGeneratorPrivate));
66
67 gobject_class->get_property = gdata_generator_get_property;
68 gobject_class->finalize = gdata_generator_finalize;
69
70 parsable_class->pre_parse_xml = pre_parse_xml;
71 parsable_class->parse_xml = parse_xml;
72 parsable_class->element_name = "generator";
73
74 /**
75 * GDataGenerator:name:
76 *
77 * A human-readable name for the generating agent.
78 *
79 * For more information, see the
80 * <ulink type="http" url="http://www.atomenabled.org/developers/syndication/atom-format-spec.php#element.generator">
81 * Atom specification</ulink>.
82 *
83 * Since: 0.4.0
84 */
85 g_object_class_install_property (gobject_class, PROP_NAME,
86 g_param_spec_string ("name",
87 "Name", "A human-readable name for the generating agent.",
88 NULL,
89 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
90
91 /**
92 * GDataGenerator:uri:
93 *
94 * An IRI reference that is relevant to the agent.
95 *
96 * For more information, see the
97 * <ulink type="http" url="http://www.atomenabled.org/developers/syndication/atom-format-spec.php#element.generator">
98 * Atom specification</ulink>.
99 *
100 * Since: 0.4.0
101 */
102 g_object_class_install_property (gobject_class, PROP_URI,
103 g_param_spec_string ("uri",
104 "URI", "An IRI reference that is relevant to the agent.",
105 NULL,
106 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
107
108 /**
109 * GDataGenerator:version:
110 *
111 * Indicates the version of the generating agent.
112 *
113 * For more information, see the
114 * <ulink type="http" url="http://www.atomenabled.org/developers/syndication/atom-format-spec.php#element.generator">
115 * Atom specification</ulink>.
116 *
117 * Since: 0.4.0
118 */
119 g_object_class_install_property (gobject_class, PROP_VERSION,
120 g_param_spec_string ("version",
121 "Version", "Indicates the version of the generating agent.",
122 NULL,
123 G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
124 }
125
126 static gint
compare_with(GDataComparable * self,GDataComparable * other)127 compare_with (GDataComparable *self, GDataComparable *other)
128 {
129 return g_strcmp0 (((GDataGenerator*) self)->priv->name, ((GDataGenerator*) other)->priv->name);
130 }
131
132 static void
gdata_generator_comparable_init(GDataComparableIface * iface)133 gdata_generator_comparable_init (GDataComparableIface *iface)
134 {
135 iface->compare_with = compare_with;
136 }
137
138 static void
gdata_generator_init(GDataGenerator * self)139 gdata_generator_init (GDataGenerator *self)
140 {
141 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_GENERATOR, GDataGeneratorPrivate);
142 }
143
144 static void
gdata_generator_finalize(GObject * object)145 gdata_generator_finalize (GObject *object)
146 {
147 GDataGeneratorPrivate *priv = GDATA_GENERATOR (object)->priv;
148
149 g_free (priv->name);
150 g_free (priv->uri);
151 g_free (priv->version);
152
153 /* Chain up to the parent class */
154 G_OBJECT_CLASS (gdata_generator_parent_class)->finalize (object);
155 }
156
157 static void
gdata_generator_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)158 gdata_generator_get_property (GObject *object, guint property_id, GValue *value, GParamSpec *pspec)
159 {
160 GDataGeneratorPrivate *priv = GDATA_GENERATOR (object)->priv;
161
162 switch (property_id) {
163 case PROP_NAME:
164 g_value_set_string (value, priv->name);
165 break;
166 case PROP_URI:
167 g_value_set_string (value, priv->uri);
168 break;
169 case PROP_VERSION:
170 g_value_set_string (value, priv->version);
171 break;
172 default:
173 /* We don't have any other property... */
174 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
175 break;
176 }
177 }
178
179 static gboolean
pre_parse_xml(GDataParsable * parsable,xmlDoc * doc,xmlNode * root_node,gpointer user_data,GError ** error)180 pre_parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *root_node, gpointer user_data, GError **error)
181 {
182 xmlChar *uri, *name;
183 GDataGeneratorPrivate *priv = GDATA_GENERATOR (parsable)->priv;
184
185 uri = xmlGetProp (root_node, (xmlChar*) "uri");
186 if (uri != NULL && *uri == '\0') {
187 xmlFree (uri);
188 return gdata_parser_error_required_property_missing (root_node, "uri", error);
189 }
190
191 name = xmlNodeListGetString (doc, root_node->children, TRUE);
192 if (name != NULL && *name == '\0') {
193 xmlFree (uri);
194 xmlFree (name);
195 return gdata_parser_error_required_content_missing (root_node, error);
196 }
197
198 priv->uri = (gchar*) uri;
199 priv->name = (gchar*) name;
200 priv->version = (gchar*) xmlGetProp (root_node, (xmlChar*) "version");
201
202 return TRUE;
203 }
204
205 static gboolean
parse_xml(GDataParsable * parsable,xmlDoc * doc,xmlNode * node,gpointer user_data,GError ** error)206 parse_xml (GDataParsable *parsable, xmlDoc *doc, xmlNode *node, gpointer user_data, GError **error)
207 {
208 /* Textual content's handled in pre_parse_xml */
209 if (node->type != XML_ELEMENT_NODE)
210 return TRUE;
211
212 return GDATA_PARSABLE_CLASS (gdata_generator_parent_class)->parse_xml (parsable, doc, node, user_data, error);
213 }
214
215 /**
216 * gdata_generator_get_name:
217 * @self: a #GDataGenerator
218 *
219 * Gets the #GDataGenerator:name property. The name will be %NULL or non-empty.
220 *
221 * Return value: (nullable): the generator's name
222 *
223 * Since: 0.4.0
224 */
225 const gchar *
gdata_generator_get_name(GDataGenerator * self)226 gdata_generator_get_name (GDataGenerator *self)
227 {
228 g_return_val_if_fail (GDATA_IS_GENERATOR (self), NULL);
229 return self->priv->name;
230 }
231
232 /**
233 * gdata_generator_get_uri:
234 * @self: a #GDataGenerator
235 *
236 * Gets the #GDataGenerator:uri property. The URI will be %NULL or non-empty.
237 *
238 * Return value: (nullable): the generator's URI, or %NULL
239 *
240 * Since: 0.4.0
241 */
242 const gchar *
gdata_generator_get_uri(GDataGenerator * self)243 gdata_generator_get_uri (GDataGenerator *self)
244 {
245 g_return_val_if_fail (GDATA_IS_GENERATOR (self), NULL);
246 return self->priv->uri;
247 }
248
249 /**
250 * gdata_generator_get_version:
251 * @self: a #GDataGenerator
252 *
253 * Gets the #GDataGenerator:version property.
254 *
255 * Return value: the generator's version, or %NULL
256 *
257 * Since: 0.4.0
258 */
259 const gchar *
gdata_generator_get_version(GDataGenerator * self)260 gdata_generator_get_version (GDataGenerator *self)
261 {
262 g_return_val_if_fail (GDATA_IS_GENERATOR (self), NULL);
263 return self->priv->version;
264 }
265