Blame gfbgraph/gfbgraph-connectable.c

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