[libgrss] Introducing GrssFeedFormatter, GrssFeedRssFormatter and GrssFeedAtomFormatter



commit 1d6b54492b30b24d7c728b6b24c2873c64887c16
Author: Roberto Guido <rguido src gnome org>
Date:   Fri Apr 25 02:38:46 2014 +0200

    Introducing GrssFeedFormatter, GrssFeedRssFormatter and GrssFeedAtomFormatter

 .../{libgrss-docs.sgml => libgrss-0.5-docs.sgml}   |    3 +
 src/Makefile.am                                    |    6 +
 src/feed-atom-formatter.c                          |  158 +++++++++++++++++
 src/feed-atom-formatter.h                          |   48 +++++
 src/feed-atom-handler.c                            |    1 +
 src/feed-enclosure.c                               |   27 ++-
 src/feed-formatter.c                               |  183 ++++++++++++++++++++
 src/feed-formatter.h                               |   56 ++++++
 src/feed-rss-formatter.c                           |  153 ++++++++++++++++
 src/feed-rss-formatter.h                           |   48 +++++
 src/feed-rss-handler.c                             |    2 +-
 src/libgrss.h                                      |    3 +
 src/utils.c                                        |    2 +-
 tests/formatter.c                                  |   90 ++++++++++
 14 files changed, 769 insertions(+), 11 deletions(-)
---
diff --git a/doc/reference/libgrss-docs.sgml b/doc/reference/libgrss-0.5-docs.sgml
similarity index 93%
rename from doc/reference/libgrss-docs.sgml
rename to doc/reference/libgrss-0.5-docs.sgml
index b8c22f3..5533cf1 100644
--- a/doc/reference/libgrss-docs.sgml
+++ b/doc/reference/libgrss-0.5-docs.sgml
@@ -39,6 +39,9 @@
     <xi:include href="xml/feeds-pool.xml"/>
     <xi:include href="xml/feeds-group.xml"/>
     <xi:include href="xml/feeds-subscriber.xml"/>
+    <xi:include href="xml/feed-formatter.xml"/>
+    <xi:include href="xml/feed-rss-formatter.xml"/>
+    <xi:include href="xml/feed-atom-formatter.xml"/>
     <xi:include href="xml/feeds-publisher.xml"/>
     <xi:include href="xml/feeds-store.xml"/>
   </part>
diff --git a/src/Makefile.am b/src/Makefile.am
index 26ff8ef..11f5bbb 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,10 +28,13 @@ sources_private_h = \
 
 sources_public_h = \
        libgrss.h                       \
+       feed-atom-formatter.h           \
        feed-channel.h                  \
        feed-enclosure.h                \
+       feed-formatter.h                \
        feed-item.h                     \
        feed-parser.h                   \
+       feed-rss-formatter.h            \
        feeds-group.h                   \
        feeds-pool.h                    \
        feeds-publisher.h               \
@@ -39,10 +42,13 @@ sources_public_h = \
        feeds-subscriber.h
 
 sources_public_c = \
+       feed-atom-formatter.c           \
        feed-channel.c                  \
        feed-enclosure.c                \
+       feed-formatter.c                \
        feed-item.c                     \
        feed-parser.c                   \
+       feed-rss-formatter.c            \
        feeds-group.c                   \
        feeds-pool.c                    \
        feeds-publisher.c               \
diff --git a/src/feed-atom-formatter.c b/src/feed-atom-formatter.c
new file mode 100644
index 0000000..4bb371d
--- /dev/null
+++ b/src/feed-atom-formatter.c
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2014, Roberto Guido <rguido src gnome org>
+ *
+ * This library 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 3 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include "feed-atom-formatter.h"
+#include "utils.h"
+
+G_DEFINE_TYPE (GrssFeedAtomFormatter, grss_feed_atom_formatter, GRSS_FEED_FORMATTER_TYPE);
+
+static gchar*
+feed_atom_formatter_format (GrssFeedFormatter *formatter)
+{
+       const gchar *str;
+       gchar *formatted;
+       time_t date;
+       GList *iter;
+       GList *items;
+       const GList *list;
+       GString *text;
+       GrssFeedChannel *channel;
+       GrssFeedItem *item;
+
+       text = g_string_new ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<feed 
xmlns=\"http://www.w3.org/2005/Atom\";>\n");
+
+       channel = grss_feed_formatter_get_channel (formatter);
+       items = grss_feed_formatter_get_items (formatter);
+
+       if (channel != NULL) {
+               str = grss_feed_channel_get_title (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<title>%s</title>\n", str);
+
+               str = grss_feed_channel_get_description (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<subtitle>%s</subtitle>\n", str);
+
+               str = grss_feed_channel_get_homepage (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<link href=\"%s\" />\n", str);
+
+               str = grss_feed_channel_get_copyright (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<rights>%s</rights>\n", str);
+
+               str = grss_feed_channel_get_editor (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<author>%s</author>\n", str);
+
+               str = grss_feed_channel_get_generator (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<generator>%s</generator>\n", str);
+
+               list = grss_feed_channel_get_contributors (channel);
+               while (list != NULL) {
+                       g_string_append_printf (text, "\t<contributor>%s</contributor>\n", (gchar*) 
list->data);
+                       list = list->next;
+               }
+
+               date = grss_feed_channel_get_update_time (channel);
+               if (date == 0)
+                       date = grss_feed_channel_get_publish_time (channel);
+               formatted = date_to_ISO8601 (date);
+               g_string_append_printf (text, "\t<updated>%s</updated>\n", formatted);
+               g_free (formatted);
+
+               str = grss_feed_channel_get_icon (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<icon>%s</icon>\n", str);
+
+               str = grss_feed_channel_get_image (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<logo>%s</logo>\n", str);
+
+               for (iter = items; iter; iter = iter->next) {
+                       item = iter->data;
+
+                       g_string_append (text, "\t<entry>\n");
+
+                       str = grss_feed_item_get_title (item);
+                       if (str != NULL)
+                               g_string_append_printf (text, "\t\t<title>%s</title>\n", str);
+
+                       str = grss_feed_item_get_id (item);
+                       if (str != NULL)
+                               g_string_append_printf (text, "\t\t<id>%s</id>\n", str);
+
+                       str = grss_feed_item_get_source (item);
+                       if (str != NULL)
+                               g_string_append_printf (text, "\t\t<link href=\"%s\" />\n", str);
+
+                       str = grss_feed_item_get_description (item);
+                       if (str != NULL)
+                               g_string_append_printf (text, "\t\t<summary>%s</summary>\n", str);
+
+                       str = grss_feed_item_get_author (item);
+                       if (str != NULL)
+                               g_string_append_printf (text, "\t\t<author>%s</author>\n", str);
+
+                       str = grss_feed_item_get_copyright (item);
+                       if (str != NULL)
+                               g_string_append_printf (text, "\t\t<rights>%s</rights>\n", str);
+
+                       list = grss_feed_item_get_contributors (item);
+                       while (list != NULL) {
+                               g_string_append_printf (text, "\t\t<contributor>%s</contributor>\n", (gchar*) 
list->data);
+                               list = list->next;
+                       }
+
+                       date = grss_feed_item_get_publish_time (item);
+                       formatted = date_to_ISO8601 (date);
+                       g_string_append_printf (text, "\t\t<published>%s</published>\n", formatted);
+                       g_free (formatted);
+
+                       g_string_append (text, "\t</entry>\n");
+               }
+       }
+
+       g_string_append (text, "</feed>");
+       return g_string_free (text, FALSE);
+}
+
+static void
+grss_feed_atom_formatter_class_init (GrssFeedAtomFormatterClass *klass)
+{
+       GrssFeedFormatterClass *formater_class = GRSS_FEED_FORMATTER_CLASS (klass);
+
+       formater_class->format = feed_atom_formatter_format;
+}
+
+static void
+grss_feed_atom_formatter_init (GrssFeedAtomFormatter *object)
+{
+}
+
+GrssFeedAtomFormatter*
+grss_feed_atom_formatter_new ()
+{
+       GrssFeedAtomFormatter *formatter;
+
+       formatter = g_object_new (GRSS_FEED_ATOM_FORMATTER_TYPE, NULL);
+       return formatter;
+}
+
diff --git a/src/feed-atom-formatter.h b/src/feed-atom-formatter.h
new file mode 100644
index 0000000..826e68c
--- /dev/null
+++ b/src/feed-atom-formatter.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014, Roberto Guido <rguido src gnome org>
+ *
+ * This library 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 3 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __GRSS_FEED_ATOM_FORMATTER_H__
+#define __GRSS_FEED_ATOM_FORMATTER_H__
+
+#include "libgrss.h"
+
+#define GRSS_FEED_ATOM_FORMATTER_TYPE          (grss_feed_atom_formatter_get_type())
+#define GRSS_FEED_ATOM_FORMATTER(o)            (G_TYPE_CHECK_INSTANCE_CAST ((o), 
GRSS_FEED_ATOM_FORMATTER_TYPE, GrssFeedAtomFormatter))
+#define GRSS_FEED_ATOM_FORMATTER_CLASS(c)      (G_TYPE_CHECK_CLASS_CAST ((c), GRSS_FEED_ATOM_FORMATTER_TYPE, 
GrssFeedAtomFormatterClass))
+#define GRSS_IS_FEED_ATOM_FORMATTER(o)         (G_TYPE_CHECK_INSTANCE_TYPE ((o), 
GRSS_FEED_ATOM_FORMATTER_TYPE))
+#define GRSS_IS_FEED_ATOM_FORMATTER_CLASS(c)   (G_TYPE_CHECK_CLASS_TYPE ((c),  
GRSS_FEED_ATOM_FORMATTER_TYPE))
+#define GRSS_FEED_ATOM_FORMATTER_GET_CLASS(o)  (G_TYPE_INSTANCE_GET_CLASS ((o), 
GRSS_FEED_ATOM_FORMATTER_TYPE, GrssFeedAtomFormatterClass))
+
+typedef struct GrssFeedAtomFormatter        GrssFeedAtomFormatter;
+typedef struct GrssFeedAtomFormatterPrivate GrssFeedAtomFormatterPrivate;
+
+struct GrssFeedAtomFormatter {
+       GrssFeedFormatter parent;
+};
+
+typedef struct {
+       GrssFeedFormatterClass parent;
+} GrssFeedAtomFormatterClass;
+
+GType                  grss_feed_atom_formatter_get_type       (void) G_GNUC_CONST;
+
+GrssFeedAtomFormatter* grss_feed_atom_formatter_new            ();
+
+#endif /* __GRSS_FEED_ATOM_FORMATTER_H__ */
+
diff --git a/src/feed-atom-handler.c b/src/feed-atom-handler.c
index 7cedb62..84b8564 100644
--- a/src/feed-atom-handler.c
+++ b/src/feed-atom-handler.c
@@ -760,6 +760,7 @@ atom10_parse_feed_updated (xmlNodePtr cur, GrssFeedChannel *feed)
        if (timestamp) {
                t = date_parse_ISO8601 (timestamp);
                grss_feed_channel_set_update_time (feed, t);
+               grss_feed_channel_set_publish_time (feed, t);
                g_free (timestamp);
        }
 }
diff --git a/src/feed-enclosure.c b/src/feed-enclosure.c
index 7a62496..632b9a9 100644
--- a/src/feed-enclosure.c
+++ b/src/feed-enclosure.c
@@ -52,7 +52,8 @@ feed_enclosure_error_quark ()
        return g_quark_from_static_string ("feed_enclosure_error");
 }
 
-static void grss_feed_enclosure_finalize (GObject *obj)
+static void
+grss_feed_enclosure_finalize (GObject *obj)
 {
        GrssFeedEnclosure *enclosure;
 
@@ -61,7 +62,8 @@ static void grss_feed_enclosure_finalize (GObject *obj)
        FREE_STRING (enclosure->priv->type);
 }
 
-static void grss_feed_enclosure_class_init (GrssFeedEnclosureClass *klass)
+static void
+grss_feed_enclosure_class_init (GrssFeedEnclosureClass *klass)
 {
        GObjectClass *gobject_class;
 
@@ -71,7 +73,8 @@ static void grss_feed_enclosure_class_init (GrssFeedEnclosureClass *klass)
        gobject_class->finalize = grss_feed_enclosure_finalize;
 }
 
-static void grss_feed_enclosure_init (GrssFeedEnclosure *node)
+static void
+grss_feed_enclosure_init (GrssFeedEnclosure *node)
 {
        node->priv = FEED_ENCLOSURE_GET_PRIVATE (node);
        memset (node->priv, 0, sizeof (GrssFeedEnclosurePrivate));
@@ -85,7 +88,8 @@ static void grss_feed_enclosure_init (GrssFeedEnclosure *node)
  *
  * Return value: a new #GrssFeedEnclosure.
  */
-GrssFeedEnclosure* grss_feed_enclosure_new (gchar *url)
+GrssFeedEnclosure*
+grss_feed_enclosure_new (gchar *url)
 {
        GrssFeedEnclosure *ret;
 
@@ -102,7 +106,8 @@ GrssFeedEnclosure* grss_feed_enclosure_new (gchar *url)
  *
  * Return value: the URL where the enclosure may be found.
  */
-const gchar* grss_feed_enclosure_get_url (GrssFeedEnclosure *enclosure)
+const gchar*
+grss_feed_enclosure_get_url (GrssFeedEnclosure *enclosure)
 {
        return (const gchar*) enclosure->priv->url;
 }
@@ -114,7 +119,8 @@ const gchar* grss_feed_enclosure_get_url (GrssFeedEnclosure *enclosure)
  *
  * To set the type of the external file.
  */
-void grss_feed_enclosure_set_format (GrssFeedEnclosure *enclosure, gchar *type)
+void
+grss_feed_enclosure_set_format (GrssFeedEnclosure *enclosure, gchar *type)
 {
        FREE_STRING (enclosure->priv->type);
        enclosure->priv->type = g_strdup (type);
@@ -128,7 +134,8 @@ void grss_feed_enclosure_set_format (GrssFeedEnclosure *enclosure, gchar *type)
  *
  * Return value: type of @enclosure.
  */
-const gchar* grss_feed_enclosure_get_format (GrssFeedEnclosure *enclosure)
+const gchar*
+grss_feed_enclosure_get_format (GrssFeedEnclosure *enclosure)
 {
        return (const gchar*) enclosure->priv->type;
 }
@@ -140,7 +147,8 @@ const gchar* grss_feed_enclosure_get_format (GrssFeedEnclosure *enclosure)
  *
  * To set the size of the embedded @enclosure.
  */
-void grss_feed_enclosure_set_length (GrssFeedEnclosure *enclosure, gsize length)
+void
+grss_feed_enclosure_set_length (GrssFeedEnclosure *enclosure, gsize length)
 {
        enclosure->priv->length = length;
 }
@@ -153,7 +161,8 @@ void grss_feed_enclosure_set_length (GrssFeedEnclosure *enclosure, gsize length)
  *
  * Return value: size of the @enclosure, in bytes.
  */
-gsize grss_feed_enclosure_get_length (GrssFeedEnclosure *enclosure)
+gsize
+grss_feed_enclosure_get_length (GrssFeedEnclosure *enclosure)
 {
        return enclosure->priv->length;
 }
diff --git a/src/feed-formatter.c b/src/feed-formatter.c
new file mode 100644
index 0000000..147b271
--- /dev/null
+++ b/src/feed-formatter.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2014, Roberto Guido <rguido src gnome org>
+ *
+ * This library 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 3 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include "feed-formatter.h"
+#include "utils.h"
+#include "feed-item.h"
+#include "feed-channel.h"
+
+#define FEED_FORMATTER_GET_PRIVATE(obj)        (G_TYPE_INSTANCE_GET_PRIVATE ((obj), 
GRSS_FEED_FORMATTER_TYPE, GrssFeedFormatterPrivate))
+
+/**
+ * SECTION: feed-formatter
+ * @short_description: abstract class to format feeds in plain rappresentation
+ *
+ * #GrssFeedFormatter is a class abstracting the ability to format a
+ * #GrssFeedChannel and related #GrssFeedItems into a plain text string, usually
+ * in XML. Subclasses implement the effective required format (e.g. RSS,
+ * Atom...)
+ */
+
+G_DEFINE_ABSTRACT_TYPE (GrssFeedFormatter, grss_feed_formatter, G_TYPE_OBJECT);
+
+struct _GrssFeedFormatterPrivate {
+       GrssFeedChannel *channel;
+       GList           *items;
+};
+
+static void
+grss_feed_formatter_class_init (GrssFeedFormatterClass *klass)
+{
+       g_type_class_add_private (klass, sizeof (GrssFeedFormatterPrivate));
+}
+
+static void
+grss_feed_formatter_init (GrssFeedFormatter *node)
+{
+       node->priv = FEED_FORMATTER_GET_PRIVATE (node);
+       node->priv->channel = NULL;
+       node->priv->items = NULL;
+}
+
+/**
+ * grss_feed_formatter_set_channel:
+ * @formatter: a #GrssFeedFormatter.
+ * @channel: the reference #GrssFeedChannel for the @formatter.
+ *
+ * Inits the #GrssFeedFormatter with the given @channel. A #GrssFeedFormatter
+ * can format a single #GrssFeedChannel each time, but may be reused by calling
+ * grss_feed_formatter_reset()
+ */
+void
+grss_feed_formatter_set_channel (GrssFeedFormatter *formatter, GrssFeedChannel *channel)
+{
+       if (formatter->priv->channel != NULL)
+               g_object_unref (formatter->priv->channel);
+
+       formatter->priv->channel = channel;
+       g_object_ref (channel);
+}
+
+/**
+ * grss_feed_formatter_get_channel:
+ * @formatter: a #GrssFeedFormatter.
+ *
+ * Gets the current #GrssFeedChannel assigned to the @formatter.
+ *
+ * Return value: (transfer none): a #GrssFeedChannel, or %NULL if none has been
+ * assigned.
+ */
+GrssFeedChannel*
+grss_feed_formatter_get_channel (GrssFeedFormatter *formatter)
+{
+       return formatter->priv->channel;
+}
+
+/**
+ * grss_feed_formatter_add_item:
+ * @formatter: a #GrssFeedFormatter.
+ * @item: a #GrssFeedItem to add into the @formatter.
+ *
+ * Adds a single #GrssFeedItem in the @formatter.
+ */
+void
+grss_feed_formatter_add_item (GrssFeedFormatter *formatter, GrssFeedItem *item)
+{
+       g_object_ref (item);
+
+       if (formatter->priv->items == NULL)
+               formatter->priv->items = g_list_prepend (formatter->priv->items, item);
+       else
+               formatter->priv->items = g_list_append (formatter->priv->items, item);
+}
+
+/**
+ * grss_feed_formatter_add_items:
+ * @formatter: a #GrssFeedFormatter.
+ * @items: (element-type GrssFeedItem): a list of #GrssFeedItems to add into
+ *         the @formatter.
+ *
+ * Adds a list of #GrssFeedItems in the @formatter.
+ */
+void
+grss_feed_formatter_add_items (GrssFeedFormatter *formatter, GList *items)
+{
+       GList *copy;
+
+       copy = g_list_copy_deep (items, (GCopyFunc) g_object_ref, NULL);
+
+       if (formatter->priv->items == NULL)
+               formatter->priv->items = copy;
+       else
+               formatter->priv->items = g_list_concat (formatter->priv->items, copy);
+}
+
+/**
+ * grss_feed_formatter_get_items:
+ * @formatter: a #GrssFeedFormatter.
+ *
+ * Gets the current #GrssFeedItems assigned to the @formatter.
+ *
+ * Return value:  (element-type GrssFeedItem) (transfer none): a list of
+ * #GrssFeedItems, or %NULL if none has been assigned.
+ */
+GList*
+grss_feed_formatter_get_items (GrssFeedFormatter *formatter)
+{
+       return formatter->priv->items;
+}
+
+/**
+ * grss_feed_formatter_reset:
+ * @formatter: a #GrssFeedFormatter.
+ *
+ * Resets the status of the #GrssFeedFormatter, cleaning up the assigned
+ * #GrssFeedChannel and related #GrssFeedItems. This way @formatter is ready to
+ * be used again with new data.
+ */
+void
+grss_feed_formatter_reset (GrssFeedFormatter *formatter)
+{
+       if (formatter->priv->channel != NULL) {
+               g_object_unref (formatter->priv->channel);
+               formatter->priv->channel = NULL;
+       }
+
+       if (formatter->priv->items != NULL) {
+               g_list_free_full (formatter->priv->items, g_object_unref);
+               formatter->priv->items = NULL;
+       }
+}
+
+/**
+ * grss_feed_formatter_format:
+ * @formatter: a #GrssFeedFormatter.
+ *
+ * Formats the assigned #GrssFeedChannel and #GrssFeedItems into a plain text
+ * string, accordly to the current #GrssFeedFormatter instance.
+ *
+ * Return value: (transfer full): a string containing the plain text
+ * rappresentation of the given channel containing the given items.
+ */
+gchar*
+grss_feed_formatter_format (GrssFeedFormatter *formatter)
+{
+       return GRSS_FEED_FORMATTER_GET_CLASS (formatter)->format (formatter);
+}
+
diff --git a/src/feed-formatter.h b/src/feed-formatter.h
new file mode 100644
index 0000000..0668447
--- /dev/null
+++ b/src/feed-formatter.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2014, Roberto Guido <rguido src gnome org>
+ *
+ * This library 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 3 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include "libgrss.h"
+
+#ifndef __FEED_FORMATTER_H__
+#define __FEED_FORMATTER_H__
+
+#define GRSS_FEED_FORMATTER_TYPE               (grss_feed_formatter_get_type())
+#define GRSS_FEED_FORMATTER(o)                 (G_TYPE_CHECK_INSTANCE_CAST ((o), GRSS_FEED_FORMATTER_TYPE, 
GrssFeedFormatter))
+#define GRSS_FEED_FORMATTER_CLASS(c)           (G_TYPE_CHECK_CLASS_CAST ((c), GRSS_FEED_FORMATTER_TYPE, 
GrssFeedFormatterClass))
+#define GRSS_IS_FEED_FORMATTER(o)              (G_TYPE_CHECK_INSTANCE_TYPE ((o), GRSS_FEED_FORMATTER_TYPE))
+#define GRSS_IS_FEED_FORMATTER_CLASS(c)                (G_TYPE_CHECK_CLASS_TYPE ((c),  
GRSS_FEED_FORMATTER_TYPE))
+#define GRSS_FEED_FORMATTER_GET_CLASS(o)       (G_TYPE_INSTANCE_GET_CLASS ((o), GRSS_FEED_FORMATTER_TYPE, 
GrssFeedFormatterClass))
+
+typedef struct _GrssFeedFormatter              GrssFeedFormatter;
+typedef struct _GrssFeedFormatterPrivate       GrssFeedFormatterPrivate;
+
+struct _GrssFeedFormatter {
+       GObject parent;
+       GrssFeedFormatterPrivate *priv;
+};
+
+typedef struct {
+       GObjectClass parent;
+
+       gchar* (*format) (GrssFeedFormatter *formatter);
+} GrssFeedFormatterClass;
+
+GType          grss_feed_formatter_get_type    () G_GNUC_CONST;
+
+void                   grss_feed_formatter_set_channel (GrssFeedFormatter *formatter, GrssFeedChannel 
*channel);
+GrssFeedChannel*       grss_feed_formatter_get_channel (GrssFeedFormatter *formatter);
+void                   grss_feed_formatter_add_item    (GrssFeedFormatter *formatter, GrssFeedItem *item);
+void                   grss_feed_formatter_add_items   (GrssFeedFormatter *formatter, GList *items);
+GList*                 grss_feed_formatter_get_items   (GrssFeedFormatter *formatter);
+void                   grss_feed_formatter_reset       (GrssFeedFormatter *formatter);
+gchar*                 grss_feed_formatter_format      (GrssFeedFormatter *formatter);
+
+#endif /* __FEED_FORMATTER_H__ */
diff --git a/src/feed-rss-formatter.c b/src/feed-rss-formatter.c
new file mode 100644
index 0000000..254174b
--- /dev/null
+++ b/src/feed-rss-formatter.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2014, Roberto Guido <rguido src gnome org>
+ *
+ * This library 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 3 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include "feed-rss-formatter.h"
+#include "utils.h"
+
+G_DEFINE_TYPE (GrssFeedRssFormatter, grss_feed_rss_formatter, GRSS_FEED_FORMATTER_TYPE);
+
+static gchar*
+feed_rss_formatter_format (GrssFeedFormatter *formatter)
+{
+       const gchar *str;
+       const gchar *title;
+       const gchar *link;
+       gchar *formatted;
+       time_t date;
+       GList *iter;
+       GList *items;
+       const GList *list;
+       GString *text;
+       GrssFeedChannel *channel;
+       GrssFeedItem *item;
+
+       /*
+               Based on http://cyber.law.harvard.edu/rss/examples/rss2sample.xml
+       */
+
+       text = g_string_new ("<?xml version=\"1.0\"?>\n<rss version=\"2.0\">\n");
+
+       channel = grss_feed_formatter_get_channel (formatter);
+       items = grss_feed_formatter_get_items (formatter);
+
+       if (channel != NULL) {
+               g_string_append_printf (text, "<channel>\n");
+
+               title = grss_feed_channel_get_title (channel);
+               if (title != NULL)
+                       g_string_append_printf (text, "\t<title>%s</title>\n", title);
+               else
+                       title = "";
+
+               str = grss_feed_channel_get_description (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<description>%s</description>\n", str);
+
+               link = grss_feed_channel_get_homepage (channel);
+               if (link != NULL)
+                       g_string_append_printf (text, "\t<link>%s</link>\n", link);
+               else
+                       link = "";
+
+               str = grss_feed_channel_get_copyright (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<copyright>%s</copyright>\n", str);
+
+               str = grss_feed_channel_get_editor (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<managingEditor>%s</managingEditor>\n", str);
+
+               str = grss_feed_channel_get_generator (channel);
+               if (str != NULL)
+                       g_string_append_printf (text, "\t<generator>%s</generator>\n", str);
+
+               date = grss_feed_channel_get_update_time (channel);
+               formatted = date_to_ISO8601 (date);
+               g_string_append_printf (text, "\t<pubDate>%s</pubDate>\n", formatted);
+               g_free (formatted);
+
+               str = grss_feed_channel_get_image (channel);
+               if (str != NULL) {
+                       g_string_append_printf (text, "\t<image>\n");
+                       g_string_append_printf (text, "\t\t<title>%s</title>\n", title);
+                       g_string_append_printf (text, "\t\t<url>%s</url>\n", str);
+                       g_string_append_printf (text, "\t\t<link>%s</link>\n", link);
+                       g_string_append_printf (text, "\t</image>\n");
+               }
+
+               for (iter = items; iter; iter = iter->next) {
+                       item = iter->data;
+
+                       g_string_append (text, "\t<item>\n");
+
+                       str = grss_feed_item_get_title (item);
+                       if (str != NULL)
+                               g_string_append_printf (text, "\t\t<title>%s</title>\n", str);
+
+                       str = grss_feed_item_get_id (item);
+                       if (str != NULL)
+                               g_string_append_printf (text, "\t\t<guid>%s</guid>\n", str);
+
+                       str = grss_feed_item_get_source (item);
+                       if (str != NULL)
+                               g_string_append_printf (text, "\t\t<link>%s</link>\n", str);
+
+                       str = grss_feed_item_get_description (item);
+                       if (str != NULL)
+                               g_string_append_printf (text, "\t\t<description>%s</description>\n", str);
+
+                       str = grss_feed_item_get_author (item);
+                       if (str != NULL)
+                               g_string_append_printf (text, "\t\t<author>%s</author>\n", str);
+
+                       date = grss_feed_item_get_publish_time (item);
+                       formatted = date_to_ISO8601 (date);
+                       g_string_append_printf (text, "\t\t<pubDate>%s</pubDate>\n", formatted);
+                       g_free (formatted);
+
+                       g_string_append (text, "\t</item>\n");
+               }
+       }
+
+       g_string_append (text, "</channel>\n</rss>");
+       return g_string_free (text, FALSE);
+}
+
+static void
+grss_feed_rss_formatter_class_init (GrssFeedRssFormatterClass *klass)
+{
+       GrssFeedFormatterClass *formater_class = GRSS_FEED_FORMATTER_CLASS (klass);
+
+       formater_class->format = feed_rss_formatter_format;
+}
+
+static void
+grss_feed_rss_formatter_init (GrssFeedRssFormatter *object)
+{
+}
+
+GrssFeedRssFormatter*
+grss_feed_rss_formatter_new ()
+{
+       GrssFeedRssFormatter *formatter;
+
+       formatter = g_object_new (GRSS_FEED_RSS_FORMATTER_TYPE, NULL);
+       return formatter;
+}
+
diff --git a/src/feed-rss-formatter.h b/src/feed-rss-formatter.h
new file mode 100644
index 0000000..5a3764b
--- /dev/null
+++ b/src/feed-rss-formatter.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2014, Roberto Guido <rguido src gnome org>
+ *
+ * This library 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 3 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#ifndef __GRSS_FEED_RSS_FORMATTER_H__
+#define __GRSS_FEED_RSS_FORMATTER_H__
+
+#include "libgrss.h"
+
+#define GRSS_FEED_RSS_FORMATTER_TYPE           (grss_feed_rss_formatter_get_type())
+#define GRSS_FEED_RSS_FORMATTER(o)             (G_TYPE_CHECK_INSTANCE_CAST ((o), 
GRSS_FEED_RSS_FORMATTER_TYPE, GrssFeedRssFormatter))
+#define GRSS_FEED_RSS_FORMATTER_CLASS(c)       (G_TYPE_CHECK_CLASS_CAST ((c), GRSS_FEED_RSS_FORMATTER_TYPE, 
GrssFeedRssFormatterClass))
+#define GRSS_IS_FEED_RSS_FORMATTER(o)          (G_TYPE_CHECK_INSTANCE_TYPE ((o), 
GRSS_FEED_RSS_FORMATTER_TYPE))
+#define GRSS_IS_FEED_RSS_FORMATTER_CLASS(c)    (G_TYPE_CHECK_CLASS_TYPE ((c),  GRSS_FEED_RSS_FORMATTER_TYPE))
+#define GRSS_FEED_RSS_FORMATTER_GET_CLASS(o)   (G_TYPE_INSTANCE_GET_CLASS ((o), 
GRSS_FEED_RSS_FORMATTER_TYPE, GrssFeedRssFormatterClass))
+
+typedef struct GrssFeedRssFormatter        GrssFeedRssFormatter;
+typedef struct GrssFeedRssFormatterPrivate GrssFeedRssFormatterPrivate;
+
+struct GrssFeedRssFormatter {
+       GrssFeedFormatter parent;
+};
+
+typedef struct {
+       GrssFeedFormatterClass parent;
+} GrssFeedRssFormatterClass;
+
+GType                  grss_feed_rss_formatter_get_type        (void) G_GNUC_CONST;
+
+GrssFeedRssFormatter*  grss_feed_rss_formatter_new             ();
+
+#endif /* __GRSS_FEED_RSS_FORMATTER_H__ */
+
diff --git a/src/feed-rss-handler.c b/src/feed-rss-handler.c
index 3a7f379..2782c24 100644
--- a/src/feed-rss-handler.c
+++ b/src/feed-rss-handler.c
@@ -226,7 +226,7 @@ parse_channel (FeedRssHandler *parser, GrssFeedChannel *feed, xmlDocPtr doc, xml
                        }
                }
                else if (!xmlStrcmp (cur->name, BAD_CAST"description")) {
-                       tmp = xhtml_extract (cur, 0, NULL);
+                       tmp = (gchar*) xmlNodeListGetString (doc, cur->xmlChildrenNode, TRUE);
                        if (tmp) {
                                grss_feed_channel_set_description (feed, tmp);
                                g_free (tmp);
diff --git a/src/libgrss.h b/src/libgrss.h
index 1d5addc..84032ca 100644
--- a/src/libgrss.h
+++ b/src/libgrss.h
@@ -35,6 +35,9 @@
 #include "feed-enclosure.h"
 #include "feed-item.h"
 #include "feed-parser.h"
+#include "feed-formatter.h"
+#include "feed-atom-formatter.h"
+#include "feed-rss-formatter.h"
 #include "feeds-store.h"
 #include "feeds-pool.h"
 #include "feeds-subscriber.h"
diff --git a/src/utils.c b/src/utils.c
index d87c78a..d5dd1c1 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -519,7 +519,7 @@ date_to_ISO8601 (time_t date)
        struct tm broken;
 
        localtime_r (&date, &broken);
-       strftime (text, 100, "%Y-%m-%dT%H:%M", &broken);
+       strftime (text, 100, "%Y-%m-%dT%H:%MZ", &broken);
        return g_strdup (text);
 }
 
diff --git a/tests/formatter.c b/tests/formatter.c
new file mode 100644
index 0000000..c88eace
--- /dev/null
+++ b/tests/formatter.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2014, Roberto Guido <rguido src gnome org>
+ *
+ * This library 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 3 of the License, or (at your option) any later version.
+ *
+ * This library 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 this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA  02110-1301, USA.
+ */
+
+#include <libgrss.h>
+
+#define TEST_CHANNEL_TITLE             "Test Feed"
+#define TEST_CHANNEL_COPYRIGHT         "Copyright 2014 John Doe"
+#define TEST_CHANNEL_DESCRIPTION       "A test fake feed"
+
+static void
+do_the_job (GrssFeedFormatter *formatter)
+{
+       gchar *xml;
+       GrssFeedChannel *channel;
+       GError *error;
+
+       channel = grss_feed_channel_new ();
+       grss_feed_channel_set_title (channel, TEST_CHANNEL_TITLE);
+       grss_feed_channel_set_copyright (channel, TEST_CHANNEL_COPYRIGHT);
+       grss_feed_channel_set_description (channel, TEST_CHANNEL_DESCRIPTION);
+
+       grss_feed_formatter_set_channel (formatter, channel);
+       g_object_unref (channel);
+
+       xml = grss_feed_formatter_format (formatter);
+       g_assert (xml != NULL);
+
+       error = NULL;
+       channel = grss_feed_channel_new_from_memory (xml, &error);
+       g_free (xml);
+
+       if (error != NULL) {
+               printf ("%s\n", error->message);
+               g_error_free (error);
+               g_test_fail ();
+       }
+
+       g_assert (channel != NULL);
+       g_assert_cmpstr (grss_feed_channel_get_title (channel), ==, TEST_CHANNEL_TITLE);
+       g_assert_cmpstr (grss_feed_channel_get_copyright (channel), ==, TEST_CHANNEL_COPYRIGHT);
+       g_assert_cmpstr (grss_feed_channel_get_description (channel), ==, TEST_CHANNEL_DESCRIPTION);
+
+       g_object_unref (channel);
+}
+
+static void
+test_format_atom ()
+{
+       GrssFeedAtomFormatter *formatter;
+
+       formatter = grss_feed_atom_formatter_new ();
+       do_the_job (GRSS_FEED_FORMATTER (formatter));
+}
+
+static void
+test_format_rss ()
+{
+       GrssFeedRssFormatter *formatter;
+
+       formatter = grss_feed_rss_formatter_new ();
+       do_the_job (GRSS_FEED_FORMATTER (formatter));
+}
+
+int
+main (int argc, char *argv[])
+{
+       g_test_init (&argc, &argv, NULL);
+
+       g_test_add_func ("/formatter/format_atom", test_format_atom);
+       g_test_add_func ("/formatter/format_rss", test_format_rss);
+
+       return g_test_run ();
+}
+


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]