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