/* sml_dev_inf_data_store.c
 *
 * Copyright (C) 2009 Michael Bell <michael.bell@opensync.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library 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 "sml_dev_inf_data_store.h"
#include <libsyncml/syncml.h>
#include "../sml_error_internals.h"

G_DEFINE_TYPE (SmlDevInfDataStore, sml_dev_inf_data_store, G_TYPE_OBJECT)

enum
{
	PROP_0,
	PROP_SOURCE_REF,
	PROP_DISPLAY_NAME,
	PROP_MAX_GUID_SIZE,
	PROP_RX_PREF,
	PROP_RX,
	PROP_TX_PREF,
	PROP_TX,
	PROP_MAX_ID,
	PROP_MAX_MEM,
	PROP_SHARED_MEM,
	PROP_SYNC_CAP,
	PROP_SUPPORT_HIERARCHICAL_SYNC
};

struct _SmlDevInfDataStorePrivate
{
	gchar*                source_ref;
	gchar*                display_name;
	gsize                 max_guid_size;
	GList*                rx;
	SmlDevInfContentType* rx_pref;
	GList*                tx;
	SmlDevInfContentType* tx_pref;
	gsize                 max_id;
	gsize                 max_mem;
	gboolean              shared_mem;
	guint32               sync_cap;
	gboolean              support_hierarchical_sync;
};

static void
sml_dev_inf_data_store_get_property (GObject    *object,
                                     guint       property_id,
                                     GValue     *value,
                                     GParamSpec *pspec)
{
	switch (property_id) {
	case PROP_SOURCE_REF:
		g_value_set_string (value, SML_DEV_INF_DATA_STORE (object)->priv->source_ref);
		break;
	case PROP_DISPLAY_NAME:
		g_value_set_string (value, SML_DEV_INF_DATA_STORE (object)->priv->display_name);
		break;
	case PROP_MAX_GUID_SIZE:
		g_value_set_uint64 (value, SML_DEV_INF_DATA_STORE (object)->priv->max_guid_size);
		break;
	case PROP_RX_PREF:
		g_value_set_object (value, SML_DEV_INF_DATA_STORE (object)->priv->rx_pref);
		break;
	case PROP_RX:
		g_value_set_pointer (value, SML_DEV_INF_DATA_STORE (object)->priv->rx);
		break;
	case PROP_TX_PREF:
		g_value_set_object (value, SML_DEV_INF_DATA_STORE (object)->priv->tx_pref);
		break;
	case PROP_TX:
		g_value_set_pointer (value, SML_DEV_INF_DATA_STORE (object)->priv->tx);
		break;
	case PROP_MAX_ID:
		g_value_set_uint64 (value, SML_DEV_INF_DATA_STORE (object)->priv->max_id);
		break;
	case PROP_MAX_MEM:
		g_value_set_uint64 (value, SML_DEV_INF_DATA_STORE (object)->priv->max_mem);
		break;
	case PROP_SHARED_MEM:
		g_value_set_boolean (value, SML_DEV_INF_DATA_STORE (object)->priv->shared_mem);
		break;
	case PROP_SYNC_CAP:
		g_value_set_uint (value, SML_DEV_INF_DATA_STORE (object)->priv->sync_cap);
		break;
	case PROP_SUPPORT_HIERARCHICAL_SYNC:
		g_value_set_boolean (value, SML_DEV_INF_DATA_STORE (object)->priv->support_hierarchical_sync);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
	}
}

static void
sml_dev_inf_data_store_set_property (GObject      *object,
                                     guint         property_id,
                                     const GValue *value,
                                     GParamSpec   *pspec)
{
	switch (property_id) {
	case PROP_SOURCE_REF:
		g_free (SML_DEV_INF_DATA_STORE (object)->priv->source_ref);
		SML_DEV_INF_DATA_STORE (object)->priv->source_ref = g_strdup (g_value_get_string (value));
		break;
	case PROP_DISPLAY_NAME:
		g_free (SML_DEV_INF_DATA_STORE (object)->priv->display_name);
		SML_DEV_INF_DATA_STORE (object)->priv->display_name = g_strdup (g_value_get_string (value));
		break;
	case PROP_MAX_GUID_SIZE:
		SML_DEV_INF_DATA_STORE (object)->priv->max_guid_size = g_value_get_uint64 (value);
		break;
	case PROP_RX_PREF:
        	if (SML_DEV_INF_DATA_STORE (object)->priv->rx_pref)
        		g_object_unref (SML_DEV_INF_DATA_STORE (object)->priv->rx_pref);
		SML_DEV_INF_DATA_STORE (object)->priv->rx_pref = g_value_get_object (value);
		g_object_ref(SML_DEV_INF_DATA_STORE (object)->priv->rx_pref);
		break;
	case PROP_RX:
		SML_DEV_INF_DATA_STORE (object)->priv->rx = (GList *) g_value_get_pointer(value);
		break;
	case PROP_TX_PREF:
        	if (SML_DEV_INF_DATA_STORE (object)->priv->tx_pref)
        		g_object_unref (SML_DEV_INF_DATA_STORE (object)->priv->tx_pref);
		SML_DEV_INF_DATA_STORE (object)->priv->tx_pref = g_value_get_object (value);
		g_object_ref(SML_DEV_INF_DATA_STORE (object)->priv->tx_pref);
		break;
	case PROP_TX:
		SML_DEV_INF_DATA_STORE (object)->priv->tx = (GList *) g_value_get_pointer(value);
		break;
	case PROP_MAX_ID:
		SML_DEV_INF_DATA_STORE (object)->priv->max_id = g_value_get_uint64 (value);
		break;
	case PROP_MAX_MEM:
		SML_DEV_INF_DATA_STORE (object)->priv->max_mem = g_value_get_uint64 (value);
		break;
	case PROP_SHARED_MEM:
		SML_DEV_INF_DATA_STORE (object)->priv->shared_mem = g_value_get_boolean (value);
		break;
	case PROP_SYNC_CAP:
		SML_DEV_INF_DATA_STORE (object)->priv->sync_cap = g_value_get_uint (value);
		break;
	case PROP_SUPPORT_HIERARCHICAL_SYNC:
		SML_DEV_INF_DATA_STORE (object)->priv->support_hierarchical_sync = g_value_get_boolean (value);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
	}
}

static void
sml_dev_inf_data_store_finalize (GObject *object)
{
	SmlDevInfDataStore *self = (SmlDevInfDataStore *) object;
	g_free(self->priv->source_ref);
	g_free(self->priv->display_name);
	g_object_unref(self->priv->rx_pref);
	g_object_unref(self->priv->tx_pref);
	while(self->priv->rx) {
		SmlDevInfContentType *ct = self->priv->rx->data;
		self->priv->rx = g_list_remove(self->priv->rx, ct);
		g_object_unref(ct);
	}
	while(self->priv->tx) {
		SmlDevInfContentType *ct = self->priv->tx->data;
		self->priv->tx = g_list_remove(self->priv->tx, ct);
		g_object_unref(ct);
	}
	/* all pointers must be NULL */
	self->priv->source_ref = NULL;
	self->priv->display_name = NULL;
	self->priv->rx_pref = NULL;
	self->priv->tx_pref = NULL;
	G_OBJECT_CLASS (sml_dev_inf_data_store_parent_class)->finalize (object);
}

static void
sml_dev_inf_data_store_class_init (SmlDevInfDataStoreClass *klass)
{
	GObjectClass *object_class = G_OBJECT_CLASS (klass);

	g_type_class_add_private (klass, sizeof (SmlDevInfDataStorePrivate));

	object_class->get_property = sml_dev_inf_data_store_get_property;
	object_class->set_property = sml_dev_inf_data_store_set_property;
	object_class->finalize     = sml_dev_inf_data_store_finalize;

	/**
	 * SmlDevInfDataStore:SourceRef:
	 *
	 * The This is the name of the local ressource. property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_SOURCE_REF,
	                                 g_param_spec_string ("SourceRef",
	                                                      "",
	                                                      "This is the name of the local ressource.",
	                                                      NULL,
	                                                      G_PARAM_READWRITE));
	/**
	 * SmlDevInfDataStore:DisplayName:
	 *
	 * The The name in the GUI. property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_DISPLAY_NAME,
	                                 g_param_spec_string ("DisplayName",
	                                                      "",
	                                                      "The name in the GUI.",
	                                                      NULL,
	                                                      G_PARAM_READWRITE));
	/**
	 * SmlDevInfDataStore:MaxGUIDSize:
	 *
	 * The The maximum size which can be used for GUIDs of synchronized item. property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_MAX_GUID_SIZE,
	                                 g_param_spec_uint64 ("MaxGUIDSize",
	                                                      "",
	                                                      "The maximum size which can be used for GUIDs of synchronized item.",
	                                                      0,
	                                                      G_MAXUINT64,
	                                                      0,
	                                                      G_PARAM_READWRITE));
	/**
	 * SmlDevInfDataStore:RxPref:
	 *
	 * The The preferred content type of the local ressource. property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_RX_PREF,
	                                 g_param_spec_object ("RxPref",
	                                                      "",
	                                                      "The preferred content type of the local ressource.",
	                                                      G_TYPE_OBJECT,
	                                                      G_PARAM_READWRITE));
	/**
	 * SmlDevInfDataStore:Rx:
	 *
	 * The The supported content types of the local ressource. property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_RX,
	                                 g_param_spec_pointer ("Rx",
	                                                       "Rx",
	                                                       "The supported content types of the local ressource.",
	                                                       G_PARAM_PRIVATE));
	/**
	 * SmlDevInfDataStore:TxPref:
	 *
	 * The The preferred content type of the remote target. property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_TX_PREF,
	                                 g_param_spec_object ("TxPref",
	                                                      "",
	                                                      "The preferred content type of the remote target.",
	                                                      G_TYPE_OBJECT,
	                                                      G_PARAM_READWRITE));
	/**
	 * SmlDevInfDataStore:Tx:
	 *
	 * The The supported content types of the remote target. property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_TX,
	                                 g_param_spec_pointer ("Tx",
	                                                       "Tx",
	                                                       "The supported content types of the remote target.",
	                                                       G_PARAM_PRIVATE));
	/**
	 * SmlDevInfDataStore:MaxID:
	 *
	 * The The maximum supported GUID for synchronized items. property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_MAX_ID,
	                                 g_param_spec_uint64 ("MaxID",
	                                                      "",
	                                                      "The maximum supported GUID for synchronized items.",
	                                                      0,
	                                                      G_MAXUINT64,
	                                                      0,
	                                                      G_PARAM_READWRITE));
	/**
	 * SmlDevInfDataStore:MaxMem:
	 *
	 * The The maximum available memory of the datastore. property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_MAX_MEM,
	                                 g_param_spec_uint64 ("MaxMem",
	                                                      "",
	                                                      "The maximum available memory of the datastore.",
	                                                      0,
	                                                      G_MAXUINT64,
	                                                      0,
	                                                      G_PARAM_READWRITE));
	/**
	 * SmlDevInfDataStore:SharedMem:
	 *
	 * The If this property is set true then the MaxMem is for the whole device. property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_SHARED_MEM,
	                                 g_param_spec_boolean ("SharedMem",
	                                                       "",
	                                                       "If this property is set true then the MaxMem is for the whole device.",
	                                                       FALSE,
	                                                       G_PARAM_READWRITE));
	/**
	 * SmlDevInfDataStore:SyncCap:
	 *
	 * The These are the SyncCaps for the data store. This is a bit field. property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_SYNC_CAP,
	                                 g_param_spec_uint ("SyncCap",
	                                                    "",
	                                                    "These are the SyncCaps for the data store. This is a bit field.",
	                                                    0,
                                                            G_MAXUINT,
                                                            0,
	                                                    G_PARAM_READWRITE));
	/**
	 * SmlDevInfDataStore:SupportsHierarchicalSync:
	 *
	 * The SupportsHierarchicalSync property.
	 */
	g_object_class_install_property (object_class,
	                                 PROP_SUPPORT_HIERARCHICAL_SYNC,
	                                 g_param_spec_boolean ("SupportsHierarchicalSync",
	                                                       "",
	                                                       "If this property is set true then hierarchical sync is supported.",
	                                                       FALSE,
	                                                       G_PARAM_READWRITE));

}

static void
sml_dev_inf_data_store_init (SmlDevInfDataStore *self)
{
	self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
	                                          SML_TYPE_DEV_INF_DATA_STORE,
	                                          SmlDevInfDataStorePrivate);
}

/**
 * sml_dev_inf_data_store_new:
 *
 * Creates a new instance of #SmlDevInfDataStore.
 *
 * Return value: the newly created #SmlDevInfDataStore instance
 */
SmlDevInfDataStore*
sml_dev_inf_data_store_new (const gchar *source_ref, GError **error)
{
	CHECK_ERROR_REF
	sml_return_val_error_if_fail(source_ref, NULL, error, SML_ERROR_GENERIC, "The name of the local ressource is missing.")
	sml_return_val_error_if_fail(strlen(source_ref) > 0, NULL, error, SML_ERROR_GENERIC, "The name of the local ressource must not be empty.")

	SmlDevInfDataStore *self = g_object_new (SML_TYPE_DEV_INF_DATA_STORE, NULL);
	sml_return_val_error_if_fail(self, NULL, error, SML_ERROR_GENERIC, "Cannot create a new instance of SmlDevInfDataStore - out of memory.")

	self->priv->source_ref = g_strdup(source_ref);
	if (!self->priv->source_ref) {
		g_object_unref(self);
		*error = g_error_new(SML_ERROR, SML_ERROR_GENERIC, "Cannot create a new instance of SmlDevInfDataStore - out of memory.");
		return NULL;
	}

	return self;
}

/**
 * sml_dev_inf_data_store_get_source_ref:
 * @self: A #SmlDevInfDataStore
 *
 * Gets the  property.
 *
 * Return value: 
 */
G_CONST_RETURN gchar*
sml_dev_inf_data_store_get_source_ref (SmlDevInfDataStore *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), NULL);
	return self->priv->source_ref;
}

/**
 * sml_dev_inf_data_store_set_source_ref:
 * @self: A #SmlDevInfDataStore
 * @sourceref:
 *
 * Sets the  property.
 */
gboolean
sml_dev_inf_data_store_set_source_ref (SmlDevInfDataStore *self,
                                      const gchar* source_ref,
                                      GError **error)
{
	CHECK_ERROR_REF
	sml_return_val_error_if_fail(SML_IS_DEV_INF_DATA_STORE (self), FALSE, error, SML_ERROR_GENERIC, "There must be a SmlDevInfDataStore object.")
	sml_return_val_error_if_fail(source_ref, FALSE, error, SML_ERROR_GENERIC, "The name of the local ressource is missing.")
	sml_return_val_error_if_fail(strlen(source_ref) > 0, FALSE, error, SML_ERROR_GENERIC, "The name of the local ressource must not be empty.")

	g_free (self->priv->source_ref);

	self->priv->source_ref = g_strdup (source_ref);
	sml_return_val_error_if_fail(self->priv->source_ref, FALSE, error, SML_ERROR_GENERIC, "The name of the local ressource is missing.")

	return TRUE;
}

/**
 * sml_dev_inf_data_store_get_display_name:
 * @self: A #SmlDevInfDataStore
 *
 * Gets the  property.
 *
 * Return value: 
 */
G_CONST_RETURN gchar*
sml_dev_inf_data_store_get_display_name (SmlDevInfDataStore *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), NULL);
	return self->priv->display_name;
}

/**
 * sml_dev_inf_data_store_set_display_name:
 * @self: A #SmlDevInfDataStore
 * @displayname:
 *
 * Sets the  property.
 */
gboolean
sml_dev_inf_data_store_set_display_name (SmlDevInfDataStore *self,
                                         const gchar* display_name,
                                         GError **error)
{
	CHECK_ERROR_REF
	sml_return_val_error_if_fail(SML_IS_DEV_INF_DATA_STORE (self), FALSE, error, SML_ERROR_GENERIC, "There must be a SmlDevInfDataStore object.")

	g_free (self->priv->display_name);

	/* normalization */
	if (display_name && strlen(display_name) == 0)
		display_name = NULL;

	self->priv->display_name = g_strdup (display_name);
	sml_return_val_error_if_fail(!display_name || self->priv->display_name, FALSE, error, SML_ERROR_GENERIC, "Cannot copy the display name - out of memory.");

	return TRUE;
}

/**
 * sml_dev_inf_data_store_get_max_guid_size:
 * @self: A #SmlDevInfDataStore
 *
 * Gets the  property.
 *
 * Return value: 
 */
gsize
sml_dev_inf_data_store_get_max_guid_size (SmlDevInfDataStore *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), 0);
	return self->priv->max_guid_size;
}

/**
 * sml_dev_inf_data_store_set_max_guid_size:
 * @self: A #SmlDevInfDataStore
 * @maxguidsize:
 *
 * Sets the  property.
 */
void
sml_dev_inf_data_store_set_max_guid_size (SmlDevInfDataStore *self,
                                          gsize max_guid_size)
{
	g_return_if_fail (SML_IS_DEV_INF_DATA_STORE (self));
	self->priv->max_guid_size = max_guid_size;
}

/**
 * sml_dev_inf_data_store_get_rx_pref:
 * @self: A #SmlDevInfDataStore
 *
 * Gets the  property.
 *
 * Return value: 
 */
SmlDevInfContentType*
sml_dev_inf_data_store_get_rx_pref (SmlDevInfDataStore *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), NULL);
	return self->priv->rx_pref;
}

/**
 * sml_dev_inf_data_store_set_rx_pref:
 * @self: A #SmlDevInfDataStore
 * @rxpref:
 *
 * Sets the  property.
 */
gboolean
sml_dev_inf_data_store_set_rx_pref (SmlDevInfDataStore *self,
                                    SmlDevInfContentType* rx_pref,
                                    GError **error)
{
	CHECK_ERROR_REF
	sml_return_val_error_if_fail (SML_IS_DEV_INF_DATA_STORE (self), FALSE, error, SML_ERROR_GENERIC, "There is no SmlDevInfDataStore object.");
	sml_return_val_error_if_fail (rx_pref, FALSE, error, SML_ERROR_GENERIC, "The SmlDevInfContentType object is missing.");
	sml_return_val_error_if_fail (SML_IS_DEV_INF_CONTENT_TYPE (rx_pref), FALSE, error, SML_ERROR_GENERIC, "The RxPref parameter must be a SmlDevInfContentType object.");

	if (self->priv->rx_pref)
		g_object_unref (self->priv->rx_pref);
	g_object_ref (rx_pref);
	self->priv->rx_pref = rx_pref;
	return TRUE;
}

/**
 * sml_dev_inf_data_store_get_tx_pref:
 * @self: A #SmlDevInfDataStore
 *
 * Gets the  property.
 *
 * Return value: 
 */
SmlDevInfContentType*
sml_dev_inf_data_store_get_tx_pref (SmlDevInfDataStore *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), NULL);
	return self->priv->tx_pref;
}

/**
 * sml_dev_inf_data_store_set_tx_pref:
 * @self: A #SmlDevInfDataStore
 * @txpref:
 *
 * Sets the  property.
 */
gboolean
sml_dev_inf_data_store_set_tx_pref (SmlDevInfDataStore *self,
                                    SmlDevInfContentType* tx_pref,
                                    GError **error)
{
	CHECK_ERROR_REF
	sml_return_val_error_if_fail (SML_IS_DEV_INF_DATA_STORE (self), FALSE, error, SML_ERROR_GENERIC, "There is no SmlDevInfDataStore object.");
	sml_return_val_error_if_fail (tx_pref, FALSE, error, SML_ERROR_GENERIC, "The SmlDevInfContentType object is missing.");
	sml_return_val_error_if_fail (SML_IS_DEV_INF_CONTENT_TYPE (tx_pref), FALSE, error, SML_ERROR_GENERIC, "The TxPref parameter must be a SmlDevInfContentType object.");

	if (self->priv->tx_pref)
		g_object_unref (self->priv->tx_pref);
	g_object_ref (tx_pref);
	self->priv->tx_pref = tx_pref;
	return TRUE;
}

/**
 * sml_dev_inf_data_store_get_max_id:
 * @self: A #SmlDevInfDataStore
 *
 * Gets the  property.
 *
 * Return value: 
 */
gsize
sml_dev_inf_data_store_get_max_id (SmlDevInfDataStore *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), 0);
	return self->priv->max_id;
}

/**
 * sml_dev_inf_data_store_set_max_id:
 * @self: A #SmlDevInfDataStore
 * @maxid:
 *
 * Sets the  property.
 */
void
sml_dev_inf_data_store_set_max_id (SmlDevInfDataStore *self,
                                   gsize max_id)
{
	g_return_if_fail (SML_IS_DEV_INF_DATA_STORE (self));
	self->priv->max_id = max_id;
}

/**
 * sml_dev_inf_data_store_get_max_mem:
 * @self: A #SmlDevInfDataStore
 *
 * Gets the  property.
 *
 * Return value: 
 */
gsize
sml_dev_inf_data_store_get_max_mem (SmlDevInfDataStore *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), 0);
	return self->priv->max_mem;
}

/**
 * sml_dev_inf_data_store_set_max_mem:
 * @self: A #SmlDevInfDataStore
 * @maxmem:
 *
 * Sets the  property.
 */
void
sml_dev_inf_data_store_set_max_mem (SmlDevInfDataStore *self,
                                    gsize max_mem)
{
	g_return_if_fail (SML_IS_DEV_INF_DATA_STORE (self));
	self->priv->max_mem = max_mem;
}

/**
 * sml_dev_inf_data_store_get_shared_mem:
 * @self: A #SmlDevInfDataStore
 *
 * Gets the  property.
 *
 * Return value: 
 */
gboolean
sml_dev_inf_data_store_get_shared_mem (SmlDevInfDataStore *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), FALSE);
	return self->priv->shared_mem;
}

/**
 * sml_dev_inf_data_store_set_shared_mem:
 * @self: A #SmlDevInfDataStore
 * @sharedmem:
 *
 * Sets the  property.
 */
void
sml_dev_inf_data_store_set_shared_mem (SmlDevInfDataStore *self,
                                       gboolean shared_mem)
{
	g_return_if_fail (SML_IS_DEV_INF_DATA_STORE (self));
	self->priv->shared_mem = shared_mem;
}

/**
 * sml_dev_inf_data_store_num_rx:
 * @self: A #SmlDevInfDataStore
 *
 * 
 */
gsize
sml_dev_inf_data_store_num_rx (SmlDevInfDataStore *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), 0);
	return g_list_length(self->priv->rx);
}

/**
 * sml_dev_inf_data_store_get_nth_rx:
 * @self: A #SmlDevInfDataStore
 *
 * 
 */
SmlDevInfContentType*
sml_dev_inf_data_store_get_nth_rx (SmlDevInfDataStore *self,
                                   gsize n)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), NULL);
	return (SmlDevInfContentType *)g_list_nth_data(self->priv->rx, n);
}

/**
 * sml_dev_inf_data_store_add_rx:
 * @self: A #SmlDevInfDataStore
 *
 * 
 */
gboolean
sml_dev_inf_data_store_add_rx (SmlDevInfDataStore *self,
                               SmlDevInfContentType *ct,
                               GError **error)
{
	CHECK_ERROR_REF
	sml_return_val_error_if_fail (SML_IS_DEV_INF_DATA_STORE (self), FALSE, error, SML_ERROR_GENERIC, "There is no SmlDevInfDataStore object.");
	sml_return_val_error_if_fail (ct, FALSE, error, SML_ERROR_GENERIC, "The SmlDevInfContentType object is missing.");
	sml_return_val_error_if_fail (SML_IS_DEV_INF_CONTENT_TYPE (ct), FALSE, error, SML_ERROR_GENERIC, "The ct parameter must be a SmlDevInfContentType object.");

	g_object_ref(ct);
	self->priv->rx = g_list_append(self->priv->rx, ct);
	sml_return_val_error_if_fail (self->priv->rx, FALSE, error, SML_ERROR_GENERIC, "Cannot add content type to Rx list of data store.");

	return TRUE;
}

/**
 * sml_dev_inf_data_store_num_tx:
 * @self: A #SmlDevInfDataStore
 *
 * 
 */
gsize
sml_dev_inf_data_store_num_tx (SmlDevInfDataStore *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), 0);
	return g_list_length(self->priv->tx);
}

/**
 * sml_dev_inf_data_store_get_nth_tx:
 * @self: A #SmlDevInfDataStore
 *
 * 
 */
SmlDevInfContentType*
sml_dev_inf_data_store_get_nth_tx (SmlDevInfDataStore *self,
                                   gsize n)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), NULL);
	return (SmlDevInfContentType *)g_list_nth_data(self->priv->tx, n);
}

/**
 * sml_dev_inf_data_store_add_tx:
 * @self: A #SmlDevInfDataStore
 *
 * 
 */
gboolean
sml_dev_inf_data_store_add_tx (SmlDevInfDataStore *self,
                               SmlDevInfContentType *ct,
                               GError **error)
{
	CHECK_ERROR_REF
	sml_return_val_error_if_fail (SML_IS_DEV_INF_DATA_STORE (self), FALSE, error, SML_ERROR_GENERIC, "There is no SmlDevInfDataStore object.");
	sml_return_val_error_if_fail (ct, FALSE, error, SML_ERROR_GENERIC, "The SmlDevInfContentType object is missing.");
	sml_return_val_error_if_fail (SML_IS_DEV_INF_CONTENT_TYPE (ct), FALSE, error, SML_ERROR_GENERIC, "The ct parameter must be a SmlDevInfContentType object.");

	g_object_ref(ct);
	self->priv->tx = g_list_append(self->priv->tx, ct);
	sml_return_val_error_if_fail (self->priv->tx, FALSE, error, SML_ERROR_GENERIC, "Cannot add content type to Tx list of data store.");

	return TRUE;
}

/**
 * sml_dev_inf_data_store_get_sync_cap:
 * @self: A #SmlDevInfDataStore
 *
 * Gets the  property.
 *
 * Return value: 
 */
gboolean
sml_dev_inf_data_store_get_sync_cap (SmlDevInfDataStore *self,
                                     SmlDevInfSyncCap sync_cap)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), FALSE);

	/* If no SyncCap is set then the SyncCap is unknown. */
	if (sync_cap == SML_DEVINF_SYNCTYPE_UNKNOWN &&
	    self->priv->sync_cap == SML_DEVINF_SYNCTYPE_UNKNOWN)
		return TRUE;

	return self->priv->sync_cap & sync_cap ? TRUE : FALSE;
}

/**
 * sml_dev_inf_data_store_set_sync_cap:
 * @self: A #SmlDevInfDataStore
 * @sharedmem:
 *
 * Sets the  property.
 */
void
sml_dev_inf_data_store_set_sync_cap (SmlDevInfDataStore *self,
                                     SmlDevInfSyncCap sync_cap,
                                     gboolean supported)
{
	g_return_if_fail (SML_IS_DEV_INF_DATA_STORE (self));

	if (sync_cap == SML_DEVINF_SYNCTYPE_UNKNOWN) {
		if (supported) {
			self->priv->sync_cap = 0;
		} else {
			/* Ignore but warn on senseless configuration ... */
			g_warning("You cannot disabled an unknown SyncCap in a data store of the device information.");
		}
	} else {
		if (supported) {
			self->priv->sync_cap = self->priv->sync_cap | sync_cap;
		} else {
			self->priv->sync_cap = self->priv->sync_cap & ~sync_cap;
		}
	}
}

/**
 * sml_dev_inf_data_store_get_support_hierarchical_sync:
 * @self: A #SmlDevInfDataStore
 *
 * Gets the  property.
 *
 * Return value: 
 */
gboolean
sml_dev_inf_data_store_get_support_hierarchical_sync (SmlDevInfDataStore *self)
{
	g_return_val_if_fail (SML_IS_DEV_INF_DATA_STORE (self), FALSE);
	return self->priv->support_hierarchical_sync;
}

/**
 * sml_dev_inf_data_store_set_support_hierarchical_sync:
 * @self: A #SmlDevInfDataStore
 * @sharedmem:
 *
 * Sets the  property.
 */
void
sml_dev_inf_data_store_set_support_hierarchical_sync (SmlDevInfDataStore *self,
                                                       gboolean supported)
{
	g_return_if_fail (SML_IS_DEV_INF_DATA_STORE (self));
	self->priv->support_hierarchical_sync = supported;
}

/**
 * sml_dev_inf_data_store_is_compliant:
 * @self: A #SmlDevInfDataStore
 * @error: A #GError
 * 
 * This is the only function of this class where you have not to provide a pointer to the error parameter.
 * If you only want to know if the data store is already compliant
 * then you can ignore the error.
 *
 * Return value: 
 */
gboolean
sml_dev_inf_data_store_is_compliant (SmlDevInfDataStore *self,
                                     GError **error)
{
	sml_return_val_error_if_fail (SML_IS_DEV_INF_DATA_STORE (self), FALSE, error, SML_ERROR_GENERIC, "There is no SmlDevInfDataStore object.");

	sml_return_val_error_if_fail (self->priv->source_ref != NULL, FALSE, error, SML_ERROR_GENERIC, "The SourceRef must be set.");
	sml_return_val_error_if_fail (strlen(self->priv->source_ref) > 0, FALSE, error, SML_ERROR_GENERIC, "The SourceRef must not be an empty string.");
	sml_return_val_error_if_fail (self->priv->rx_pref, FALSE, error, SML_ERROR_GENERIC, "The RxPref content type must be set.");
	sml_return_val_error_if_fail (SML_IS_DEV_INF_CONTENT_TYPE(self->priv->rx_pref), FALSE, error, SML_ERROR_GENERIC, "The RxPref content type must be a SmlDevInfContentType object.");
	sml_return_val_error_if_fail (self->priv->tx_pref, FALSE, error, SML_ERROR_GENERIC, "The TxPref content type must be set.");
	sml_return_val_error_if_fail (SML_IS_DEV_INF_CONTENT_TYPE(self->priv->tx_pref), FALSE, error, SML_ERROR_GENERIC, "The TxPref content type must be a SmlDevInfContentType object.");
	sml_return_val_error_if_fail (self->priv->sync_cap > 0, FALSE, error, SML_ERROR_GENERIC, "There must be at minimum one supported SyncCap.");

	return TRUE;
}

