1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
2 /*
3 * GData Client
4 * Copyright (C) 2014 Carlos Garnacho <carlosg@gnome.org>
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-freebase-query
22 * @short_description: GData Freebase query object
23 * @stability: Stable
24 * @include: gdata/services/freebase/gdata-freebase-query.h
25 *
26 * #GDataFreebaseQuery represents a MQL query specific to the Google Freebase service.
27 *
28 * This implementation of #GDataQuery respects the gdata_query_set_max_results() call.
29 *
30 * For more details of Google Freebase API, see the <ulink type="http" url="https://developers.google.com/freebase/v1/">
31 * online documentation</ulink>.
32 *
33 * Since: 0.15.1
34 * Deprecated: 0.17.7: Google Freebase has been permanently shut down.
35 */
36
37 #include <config.h>
38 #include <glib.h>
39 #include <glib/gi18n-lib.h>
40 #include <string.h>
41 #include <json-glib/json-glib.h>
42
43 #include "gdata-freebase-query.h"
44 #include "gdata-query.h"
45 #include "gdata-parser.h"
46 #include "gdata-private.h"
47
48 G_GNUC_BEGIN_IGNORE_DEPRECATIONS
49
50 static void gdata_freebase_query_finalize (GObject *self);
51 static void gdata_freebase_query_set_property (GObject *self, guint prop_id, const GValue *value, GParamSpec *pspec);
52 static void gdata_freebase_query_get_property (GObject *self, guint prop_id, GValue *value, GParamSpec *pspec);
53 static void get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started);
54
55 struct _GDataFreebaseQueryPrivate {
56 /* These params are here not in GDataQuery due of differently named query params for JSON protocols therefore need for different parse_uri */
57 GVariant *variant;
58 JsonNode *query_node;
59 };
60
61 enum {
62 PROP_VARIANT = 1,
63 };
64
G_DEFINE_TYPE(GDataFreebaseQuery,gdata_freebase_query,GDATA_TYPE_QUERY)65 G_DEFINE_TYPE (GDataFreebaseQuery, gdata_freebase_query, GDATA_TYPE_QUERY)
66
67 static void
68 gdata_freebase_query_class_init (GDataFreebaseQueryClass *klass)
69 {
70 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
71 GDataQueryClass *query_class = GDATA_QUERY_CLASS (klass);
72
73 g_type_class_add_private (klass, sizeof (GDataFreebaseQueryPrivate));
74
75 gobject_class->finalize = gdata_freebase_query_finalize;
76 gobject_class->set_property = gdata_freebase_query_set_property;
77 gobject_class->get_property = gdata_freebase_query_get_property;
78
79 query_class->get_query_uri = get_query_uri;
80
81 /**
82 * GDataFreebaseQuery:variant:
83 *
84 * Variant containing the MQL query. The variant is a very generic container of type "a{smv}",
85 * containing (possibly nested) Freebase schema types and values.
86 *
87 * Since: 0.15.1
88 * Deprecated: 0.17.7: Google Freebase has been permanently shut down.
89 */
90 g_object_class_install_property (gobject_class, PROP_VARIANT,
91 g_param_spec_variant ("variant",
92 "Variant",
93 "Variant to construct the query from.",
94 G_VARIANT_TYPE ("a{smv}"), NULL,
95 G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
96 G_PARAM_DEPRECATED));
97 }
98
99 static void
gdata_freebase_query_init(GDataFreebaseQuery * self)100 gdata_freebase_query_init (GDataFreebaseQuery *self)
101 {
102 self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GDATA_TYPE_FREEBASE_QUERY, GDataFreebaseQueryPrivate);
103
104 /* https://developers.google.com/freebase/v1/search#cursor */
105 _gdata_query_set_pagination_type (GDATA_QUERY (self),
106 GDATA_QUERY_PAGINATION_INDEXED);
107 }
108
109 static void
gdata_freebase_query_finalize(GObject * self)110 gdata_freebase_query_finalize (GObject *self)
111 {
112 GDataFreebaseQueryPrivate *priv = GDATA_FREEBASE_QUERY (self)->priv;
113
114 if (priv->variant != NULL)
115 g_variant_unref (priv->variant);
116 if (priv->query_node != NULL)
117 json_node_free (priv->query_node);
118 /* Chain up to the parent class */
119 G_OBJECT_CLASS (gdata_freebase_query_parent_class)->finalize (self);
120 }
121
122 static void
gdata_freebase_query_set_property(GObject * self,guint prop_id,const GValue * value,GParamSpec * pspec)123 gdata_freebase_query_set_property (GObject *self, guint prop_id, const GValue *value, GParamSpec *pspec)
124 {
125 GDataFreebaseQueryPrivate *priv = GDATA_FREEBASE_QUERY (self)->priv;
126
127 switch (prop_id) {
128 case PROP_VARIANT:
129 priv->variant = g_value_get_variant (value);
130 if (priv->variant)
131 priv->query_node = json_gvariant_serialize (priv->variant);
132 break;
133 default:
134 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
135 break;
136 }
137 }
138
139 static void
gdata_freebase_query_get_property(GObject * self,guint prop_id,GValue * value,GParamSpec * pspec)140 gdata_freebase_query_get_property (GObject *self, guint prop_id, GValue *value, GParamSpec *pspec)
141 {
142 GDataFreebaseQueryPrivate *priv = GDATA_FREEBASE_QUERY (self)->priv;
143
144 switch (prop_id) {
145 case PROP_VARIANT:
146 g_value_set_variant (value, priv->variant);
147 break;
148 default:
149 G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec);
150 break;
151 }
152 }
153
154 static void
get_query_uri(GDataQuery * self,const gchar * feed_uri,GString * query_uri,gboolean * params_started)155 get_query_uri (GDataQuery *self, const gchar *feed_uri, GString *query_uri, gboolean *params_started)
156 {
157 GDataFreebaseQueryPrivate *priv = GDATA_FREEBASE_QUERY (self)->priv;
158 const gchar *query;
159
160 #define APPEND_SEP g_string_append_c (query_uri, (*params_started == FALSE) ? '?' : '&'); *params_started = TRUE;
161
162 query = gdata_query_get_q (self);
163
164 if (query != NULL) {
165 APPEND_SEP;
166 g_string_append (query_uri, "query=");
167 g_string_append (query_uri, query);
168 } else if (priv->query_node != NULL) {
169 JsonGenerator *generator;
170 JsonNode *copy;
171 gchar *json;
172 guint limit;
173
174 copy = json_node_copy (priv->query_node);
175
176 limit = gdata_query_get_max_results (self);
177
178 if (limit > 0) {
179 JsonNode *limit_node;
180 JsonObject *object;
181
182 limit_node = json_node_new (JSON_NODE_VALUE);
183 json_node_set_int (limit_node, limit);
184
185 object = json_node_get_object (copy);
186 json_object_set_member (object, "limit", limit_node);
187 }
188
189 generator = json_generator_new ();
190 json_generator_set_root (generator, copy);
191 json = json_generator_to_data (generator, NULL);
192 g_object_unref (generator);
193
194 APPEND_SEP;
195 g_string_append (query_uri, "query=");
196 g_string_append (query_uri, json);
197 g_free (json);
198 }
199
200 /* We don't chain up with parent class get_query_uri because it uses
201 * GData protocol parameters and they aren't compatible with newest API family
202 */
203 #undef APPEND_SEP
204 }
205
206 /**
207 * gdata_freebase_query_new:
208 * @mql: a MQL query string
209 *
210 * Creates a new #GDataFreebaseQuery with the MQL query provided in @mql. MQL
211 * is a JSON-based query language, analogous to SPARQL. To learn more about MQL,
212 * see the <ulink type="http" url="https://developers.google.com/freebase/v1/mql-overview">
213 * MQL overview</ulink> and <ulink type="http" url="https://developers.google.com/freebase/v1/mql-cookbook">
214 * cookbook</ulink>.
215 *
216 * For detailed information on Freebase schemas, The <ulink type="http" url="http://www.freebase.com/schema">"Schema"
217 * section</ulink> on the main site allows for natural search and navigation through the multiple data properties and domains.
218 *
219 * Return value: (transfer full): a new #GDataFreebaseQuery
220 *
221 * Since: 0.15.1
222 * Deprecated: 0.17.7: Google Freebase has been permanently shut down.
223 */
224 GDataFreebaseQuery *
gdata_freebase_query_new(const gchar * mql)225 gdata_freebase_query_new (const gchar *mql)
226 {
227 g_return_val_if_fail (mql != NULL, NULL);
228
229 return g_object_new (GDATA_TYPE_FREEBASE_QUERY, "q", mql, NULL);
230 }
231
232 /**
233 * gdata_freebase_query_new_from_variant:
234 * @variant: a variant containing the MQL query structure
235 *
236 * Creates a new #GDataFreebaseQuery with the MQL query provided in a serialized form as @variant
237 * of type "a{smv}" containing the JSON data tree of a MQL query. One convenient way
238 * to build the variant is using json_gvariant_serialize() from a #JsonNode. For more information
239 * about MQL, see gdata_freebase_query_new().
240 *
241 * #GDataFreebaseQuery takes ownership on @variant, if it has a floating reference, it will be sunk.
242 * Otherwise an extra reference will be added.
243 *
244 * Return value: (transfer full): a new #GDataFreebaseQuery
245 *
246 * Since: 0.15.1
247 * Deprecated: 0.17.7: Google Freebase has been permanently shut down.
248 */
249 GDataFreebaseQuery *
gdata_freebase_query_new_from_variant(GVariant * variant)250 gdata_freebase_query_new_from_variant (GVariant *variant)
251 {
252 g_return_val_if_fail (variant != NULL, NULL);
253
254 return g_object_new (GDATA_TYPE_FREEBASE_QUERY,
255 "variant", g_variant_ref_sink (variant),
256 NULL);
257 }
258
259 G_GNUC_END_IGNORE_DEPRECATIONS
260