/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 8; tab-width: 8 -*- */ /* * libgfbgraph - GObject library for Facebook Graph API * Copyright (C) 2013 Álvaro Peña * * GFBGraph is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * GFBGraph is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with GFBGraph. If not, see . */ /** * SECTION:gfbgraph-connectable * @title: GFBGraphConnectable * @short_description: Connectable interface for nodes * @include: gfbgraph/gfbgraph.h * * #GFBGraphConnectable interface allow the connection between nodes. * You can see the posible (not necesary implemented) connections in * the section "Connections" in any node object in the * Facebook Graph API documentation **/ #include "gfbgraph-connectable.h" #include "gfbgraph-node.h" #include G_DEFINE_INTERFACE (GFBGraphConnectable, gfbgraph_connectable, GFBGRAPH_TYPE_NODE) static void gfbgraph_connectable_default_init (GFBGraphConnectableInterface *iface) { iface->connections = NULL; iface->get_connection_post_params = NULL; iface->parse_connected_data = NULL; } static GHashTable* get_connections (GFBGraphConnectableInterface *iface) { /* The GHashTable contains the connections for a node. * The key must be the g_type_name() of a GFBGRAPH_TYPE_NODE, and the value * must be the function name to call in order to retrieve the nodes connected * to the GFBGraphNode indicated by GFBGRAPH_TYPE_NODE. */ GHashTable *connections; connections = iface->connections; /* If no connections... Why you implement this iface? */ g_assert (g_hash_table_size (connections) > 0); return connections; } /** * gfbgraph_connectable_get_connection_post_params: * @self: a #GFBGraphConnectable. * @node_type: a #GType, required a #GFBGRAPH_TYPE_NODE or children. * * Get the params to be inserted in a request to the Facebook Graph API * in order to append the node @self to a node of type @node_type. * * Returns: (transfer full): A string based #GHashTable with the params and his values or %NULL. **/ GHashTable* gfbgraph_connectable_get_connection_post_params (GFBGraphConnectable *self, GType node_type) { GFBGraphConnectableInterface *iface; g_return_val_if_fail (GFBGRAPH_IS_CONNECTABLE (self), NULL); g_return_val_if_fail (g_type_is_a (node_type, GFBGRAPH_TYPE_NODE), NULL); g_return_val_if_fail (gfbgraph_connectable_is_connectable_to (self, node_type), NULL); iface = GFBGRAPH_CONNECTABLE_GET_IFACE (self); g_assert (iface->get_connection_post_params != NULL); return iface->get_connection_post_params (self, node_type); } /** * gfbgraph_connectable_parse_connected_data: * @self: a #GFBGraphConnectable. * @payload: a const #gchar with the response string from the Facebook Graph API. * @error: (allow-none): a #GError. * * Parse the response contained in @payload when a gfbgraph_node_get_connection_nodes() was * executed. * * Returns: (element-type GFBGraphNode) (transfer full): a newly-allocated #GList of #GFBGraphNode created from the @payload or %NULL. **/ GList* gfbgraph_connectable_parse_connected_data (GFBGraphConnectable *self, const gchar *payload, GError **error) { GFBGraphConnectableInterface *iface; g_return_val_if_fail (GFBGRAPH_IS_CONNECTABLE (self), NULL); iface = GFBGRAPH_CONNECTABLE_GET_IFACE (self); g_assert (iface->parse_connected_data != NULL); return iface->parse_connected_data (self, payload, error); } /** * gfbgraph_connectable_is_connectable_to: * @self: a #GFBGraphConnectable. * @node_type: a #GType, required a #GFBGRAPH_TYPE_NODE or children. * * Check if @self object, normally a #GFBGraphNode implementing the #GFBGraphConnectable interface, * has the possibility to be connected to another node of type @node_type. * * Returns: %TRUE in case that the @self object can be connected to a node of type @node_type, * %FALSE otherwise. **/ gboolean gfbgraph_connectable_is_connectable_to (GFBGraphConnectable *self, GType node_type) { GFBGraphConnectableInterface *iface; GHashTable *connections; g_return_val_if_fail (GFBGRAPH_IS_CONNECTABLE (self), FALSE); g_return_val_if_fail (g_type_is_a (node_type, GFBGRAPH_TYPE_NODE), FALSE); iface = GFBGRAPH_CONNECTABLE_GET_IFACE (self); connections = get_connections (iface); return g_hash_table_contains (connections, g_type_name (node_type)); } /** * gfbgraph_connectable_get_connection_path: * @self: a #GFBGraphConnectable. * @node_type: a #GType, required a #GFBGRAPH_TYPE_NODE or children. * * Get the Facebook Graph API function path to retrieve the nodes connected with @node_type * managed by the #GFBGraphConnectable object. * * Returns: (transfer none): a const #gchar with the function path or %NULL. **/ const gchar* gfbgraph_connectable_get_connection_path (GFBGraphConnectable *self, GType node_type) { GFBGraphConnectableInterface *iface; GHashTable *connections; g_return_val_if_fail (GFBGRAPH_IS_CONNECTABLE (self), NULL); g_return_val_if_fail (g_type_is_a (node_type, GFBGRAPH_TYPE_NODE), NULL); g_return_val_if_fail (gfbgraph_connectable_is_connectable_to (self, node_type), NULL); iface = GFBGRAPH_CONNECTABLE_GET_IFACE (self); connections = get_connections (iface); return (const gchar *) g_hash_table_lookup (connections, g_type_name (node_type)); } /** * gfbgraph_connectable_default_parse_connected_data: * @self: a #GFBGraphConnectable. * @payload: a const #gchar with the response string from the Facebook Graph API. * @error: (allow-none): a #GError or %NULL. * * In most cases, #GFBGraphConnectable implementers can use this function in order to parse * the response when a gfbgraph_node_get_connection_nodes() is executed and the * gfbgraph_connectable_parse_connected_data() was called. * * Normally, Facebook Graph API returns the connections in the same way, using JSON objects, * with a root object called "data". * * Returns: (element-type GFBGraphNode) (transfer full): a newly-allocated #GList of #GFBGraphNode with the same #GType as @self. **/ GList* gfbgraph_connectable_default_parse_connected_data (GFBGraphConnectable *self, const gchar *payload, GError **error) { GList *nodes_list = NULL; JsonParser *jparser; GType node_type; node_type = G_OBJECT_TYPE (self); jparser = json_parser_new (); if (json_parser_load_from_data (jparser, payload, -1, error)) { JsonNode *root_jnode; JsonObject *main_jobject; JsonArray *nodes_jarray; int i = 0; root_jnode = json_parser_get_root (jparser); main_jobject = json_node_get_object (root_jnode); nodes_jarray = json_object_get_array_member (main_jobject, "data"); for (i = 0; i < json_array_get_length (nodes_jarray); i++) { JsonNode *jnode; GFBGraphNode *node; jnode = json_array_get_element (nodes_jarray, i); node = GFBGRAPH_NODE (json_gobject_deserialize (node_type, jnode)); nodes_list = g_list_append (nodes_list, node); } } g_clear_object (&jparser); return nodes_list; }