/* * Copyright (C) 2012 Red Hat, Inc. * * 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 2.1 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 St, Fifth Floor, Boston, MA 02110-1301 USA * * Author: Debarshi Ray */ #include "config.h" #include "log-iter-xml-internal.h" struct _TplLogIterXmlPriv { GList *dates; GList *events; GList *next_date; GList *next_event; TpAccount *account; TplEntity *target; TplLogStore *store; gint type_mask; }; enum { PROP_ACCOUNT = 1, PROP_STORE, PROP_TARGET, PROP_TYPE_MASK }; G_DEFINE_TYPE (TplLogIterXml, tpl_log_iter_xml, TPL_TYPE_LOG_ITER); static GList * tpl_log_iter_xml_get_events (TplLogIter *iter, guint num_events, GError **error) { TplLogIterXmlPriv *priv; GList *events; guint i; priv = TPL_LOG_ITER_XML (iter)->priv; events = NULL; if (priv->dates == NULL) { priv->dates = _tpl_log_store_get_dates (priv->store, priv->account, priv->target, priv->type_mask); priv->next_date = g_list_last (priv->dates); } i = 0; while (i < num_events) { TplEvent *event; if (priv->next_event == NULL) { if (priv->next_date == NULL) break; g_list_free_full (priv->events, g_object_unref); priv->events = _tpl_log_store_get_events_for_date (priv->store, priv->account, priv->target, priv->type_mask, (GDate *) priv->next_date->data); priv->next_event = g_list_last (priv->events); priv->next_date = g_list_previous (priv->next_date); } event = TPL_EVENT (priv->next_event->data); events = g_list_prepend (events, g_object_ref (event)); i++; priv->next_event = g_list_previous (priv->next_event); } return events; } static void tpl_log_iter_xml_rewind (TplLogIter *iter, guint num_events, GError **error) { GList *e; TplLogIterXmlPriv *priv; guint i; priv = TPL_LOG_ITER_XML (iter)->priv; e = NULL; /* Set e to the last event that was returned */ if (priv->next_event == NULL) e = priv->events; else e = g_list_next (priv->next_event); i = 0; while (i < num_events) { if (e == NULL) { GList *d; if (priv->next_date == NULL) d = priv->dates; else d = g_list_next (priv->next_date); /* This can happen if get_events was never called or called * with num_events == 0 */ if (d == NULL) break; g_list_free_full (priv->events, g_object_unref); priv->events = NULL; priv->next_event = NULL; /* Rollback the priv->next_date */ priv->next_date = d; /* Rollback the current date (ie. d) */ d = g_list_next (d); if (d == NULL) break; priv->events = _tpl_log_store_get_events_for_date (priv->store, priv->account, priv->target, priv->type_mask, (GDate *) d->data); e = priv->events; } priv->next_event = e; e = g_list_next (e); i++; } } static void tpl_log_iter_xml_dispose (GObject *object) { TplLogIterXmlPriv *priv; priv = TPL_LOG_ITER_XML (object)->priv; g_list_free_full (priv->dates, (GDestroyNotify) g_date_free); priv->dates = NULL; g_list_free_full (priv->events, g_object_unref); priv->events = NULL; g_clear_object (&priv->account); g_clear_object (&priv->store); g_clear_object (&priv->target); G_OBJECT_CLASS (tpl_log_iter_xml_parent_class)->dispose (object); } static void tpl_log_iter_xml_finalize (GObject *object) { G_OBJECT_CLASS (tpl_log_iter_xml_parent_class)->finalize (object); } static void tpl_log_iter_xml_get_property (GObject *object, guint param_id, GValue *value, GParamSpec *pspec) { TplLogIterXmlPriv *priv; priv = TPL_LOG_ITER_XML (object)->priv; switch (param_id) { case PROP_ACCOUNT: g_value_set_object (value, priv->account); break; case PROP_STORE: g_value_set_object (value, priv->store); break; case PROP_TARGET: g_value_set_object (value, priv->target); break; case PROP_TYPE_MASK: g_value_set_int (value, priv->type_mask); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void tpl_log_iter_xml_set_property (GObject *object, guint param_id, const GValue *value, GParamSpec *pspec) { TplLogIterXmlPriv *priv; priv = TPL_LOG_ITER_XML (object)->priv; switch (param_id) { case PROP_ACCOUNT: priv->account = g_value_dup_object (value); break; case PROP_STORE: priv->store = g_value_dup_object (value); break; case PROP_TARGET: priv->target = g_value_dup_object (value); break; case PROP_TYPE_MASK: priv->type_mask = g_value_get_int (value); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec); break; } } static void tpl_log_iter_xml_init (TplLogIterXml *iter) { iter->priv = G_TYPE_INSTANCE_GET_PRIVATE (iter, TPL_TYPE_LOG_ITER_XML, TplLogIterXmlPriv); } static void tpl_log_iter_xml_class_init (TplLogIterXmlClass *klass) { GObjectClass *object_class = G_OBJECT_CLASS (klass); TplLogIterClass *log_iter_class = TPL_LOG_ITER_CLASS (klass); GParamSpec *param_spec; object_class->dispose = tpl_log_iter_xml_dispose; object_class->finalize = tpl_log_iter_xml_finalize; object_class->get_property = tpl_log_iter_xml_get_property; object_class->set_property = tpl_log_iter_xml_set_property; log_iter_class->get_events = tpl_log_iter_xml_get_events; log_iter_class->rewind = tpl_log_iter_xml_rewind; param_spec = g_param_spec_object ("account", "Account", "The account whose logs are to be traversed", TP_TYPE_ACCOUNT, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_ACCOUNT, param_spec); param_spec = g_param_spec_object ("store", "Store", "The storage backend from which the logs are to be retrieved", TPL_TYPE_LOG_STORE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_STORE, param_spec); param_spec = g_param_spec_object ("target", "Target", "The target entity with which the account interacted", TPL_TYPE_ENTITY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TARGET, param_spec); param_spec = g_param_spec_int ("type-mask", "Type Mask", "A bitmask to filter the events to be retrieved", 1, 0xffff, TPL_EVENT_MASK_ANY, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); g_object_class_install_property (object_class, PROP_TYPE_MASK, param_spec); g_type_class_add_private (klass, sizeof (TplLogIterXmlPriv)); } TplLogIter * tpl_log_iter_xml_new (TplLogStore *store, TpAccount *account, TplEntity *target, gint type_mask) { return g_object_new (TPL_TYPE_LOG_ITER_XML, "store", store, "account", account, "target", target, "type-mask", type_mask, NULL); }